Bug 143038 Make users can scroll contents horizontally with vertical wheel operation with a modifier r=smaug

This patch declares a new default action, "horizontal scroll", this scrolls
content horizontally with deltaY of wheel events and ignores deltaX and deltaZ.
This is used for default action with Shift key in default setting except on
macOS. On macOS, legacy mouse's vertical wheel operation with Shift key causes
native horizontal wheel event.  Therefore, we don't need to use this new
default action on macOS.  Additionally, old default action with Shift key,
navigating history, is moved to with Alt key.  This makes same settings between
macOS and the others.  So, this is better for users who use macOS and another
OS and web app developers who check wheel events only on macOS or other
platform(s).

For simpler implementation, default action handlers moves deltaY values to
deltaX values temporarily *only* while they handle wheel events.  This is
performed by AutoWheelDeltaAdjuster and restored after handling it
automatically.

So, in other words, even if default action is "horizontal scroll", web apps
receives wheel events whose deltaY is not zero but its content will be
scrolled horizontally.  This is same as Chromium, so, this behavior shouldn't
cause any incompatible behavior with it.

MozReview-Commit-ID: E4X3yZzLEAl

--HG--
extra : rebase_source : e20d854c6b0a181ad4c9e7304bd9ad14256481ff
This commit is contained in:
Masayuki Nakano 2017-10-05 01:12:35 +09:00
Родитель eed8c6dab2
Коммит 16fd3a84a4
11 изменённых файлов: 681 добавлений и 128 удалений

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

@ -620,25 +620,32 @@ pref("browser.snapshots.limit", 0);
// 1: Scrolling contents
// 2: Go back or go forward, in your history
// 3: Zoom in or out.
// 4: Treat vertical wheel as horizontal scroll
#ifdef XP_MACOSX
// On OS X, if the wheel has one axis only, shift+wheel comes through as a
// On macOS, if the wheel has one axis only, shift+wheel comes through as a
// horizontal scroll event. Thus, we can't assign anything other than normal
// scrolling to shift+wheel.
pref("mousewheel.with_alt.action", 2);
pref("mousewheel.with_shift.action", 1);
pref("mousewheel.with_alt.action", 2);
// On MacOS X, control+wheel is typically handled by system and we don't
// receive the event. So, command key which is the main modifier key for
// acceleration is the best modifier for zoom-in/out. However, we should keep
// the control key setting for backward compatibility.
pref("mousewheel.with_meta.action", 3); // command key on Mac
// Disable control-/meta-modified horizontal mousewheel events, since
// those are used on Mac as part of modified swipe gestures (e.g.
// Left swipe+Cmd = go back in a new tab).
// Disable control-/meta-modified horizontal wheel events, since those are
// used on Mac as part of modified swipe gestures (e.g. Left swipe+Cmd is
// "go back" in a new tab).
pref("mousewheel.with_control.action.override_x", 0);
pref("mousewheel.with_meta.action.override_x", 0);
#else
pref("mousewheel.with_alt.action", 1);
pref("mousewheel.with_shift.action", 2);
// On the other platforms (non-macOS), user may use legacy mouse which supports
// only vertical wheel but want to scroll horizontally. For such users, we
// should provide horizontal scroll with shift+wheel (same as Chrome).
// However, shift+wheel was used for navigating history. For users who want
// to keep using this feature, let's enable it with alt+wheel. This is better
// for consistency with macOS users.
pref("mousewheel.with_shift.action", 4);
pref("mousewheel.with_alt.action", 2);
pref("mousewheel.with_meta.action", 1); // win key on Win, Super/Hyper on Linux
#endif
pref("mousewheel.with_control.action",3);

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

@ -3265,6 +3265,20 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
}
WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent();
MOZ_ASSERT(wheelEvent);
// When APZ is enabled, the actual scroll animation might be handled by
// the compositor.
WheelPrefs::Action action =
wheelEvent->mFlags.mHandledByAPZ ?
WheelPrefs::ACTION_NONE :
WheelPrefs::GetInstance()->ComputeActionFor(wheelEvent);
// Make the wheel event a horizontal scroll event. I.e., deltaY values
// are set to deltaX and deltaY and deltaZ values are set to 0.
// When AutoWheelDeltaAdjuster instance is destroyed, the delta values
// are restored and make overflow deltaX becomes 0.
AutoWheelDeltaAdjuster adjuster(*wheelEvent);
// Check if the frame to scroll before checking the default action
// because if the scroll target is a plugin, the default action should be
@ -3273,20 +3287,14 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
ComputeScrollTarget(mCurrentTarget, wheelEvent,
COMPUTE_DEFAULT_ACTION_TARGET);
nsPluginFrame* pluginFrame = do_QueryFrame(frameToScroll);
// When APZ is enabled, the actual scroll animation might be handled by
// the compositor.
WheelPrefs::Action action;
if (pluginFrame) {
MOZ_ASSERT(pluginFrame->WantsToHandleWheelEventAsDefaultAction());
action = WheelPrefs::ACTION_SEND_TO_PLUGIN;
} else if (wheelEvent->mFlags.mHandledByAPZ) {
action = WheelPrefs::ACTION_NONE;
} else {
action = WheelPrefs::GetInstance()->ComputeActionFor(wheelEvent);
}
switch (action) {
case WheelPrefs::ACTION_SCROLL: {
case WheelPrefs::ACTION_SCROLL:
case WheelPrefs::ACTION_HORIZONTAL_SCROLL: {
// For scrolling of default action, we should honor the mouse wheel
// transaction.
@ -5657,11 +5665,10 @@ void
EventStateManager::WheelPrefs::Reset()
{
memset(mInit, 0, sizeof(mInit));
}
EventStateManager::WheelPrefs::Index
EventStateManager::WheelPrefs::GetIndexFor(WidgetWheelEvent* aEvent)
EventStateManager::WheelPrefs::GetIndexFor(const WidgetWheelEvent* aEvent)
{
if (!aEvent) {
return INDEX_DEFAULT;
@ -5759,9 +5766,12 @@ EventStateManager::WheelPrefs::Init(EventStateManager::WheelPrefs::Index aIndex)
// Compute action values overridden by .override_x pref.
// At present, override is possible only for the x-direction
// because this pref is introduced mainly for tilt wheels.
// Note that ACTION_HORIZONTAL_SCROLL isn't a valid value for this pref
// because it affects only to deltaY.
prefNameAction.AppendLiteral(".override_x");
int32_t actionOverrideX = Preferences::GetInt(prefNameAction.get(), -1);
if (actionOverrideX < -1 || actionOverrideX > int32_t(ACTION_LAST)) {
if (actionOverrideX < -1 || actionOverrideX > int32_t(ACTION_LAST) ||
actionOverrideX == ACTION_HORIZONTAL_SCROLL) {
NS_WARNING("Unsupported action override pref value, didn't override.");
actionOverrideX = -1;
}
@ -5770,6 +5780,25 @@ EventStateManager::WheelPrefs::Init(EventStateManager::WheelPrefs::Index aIndex)
: static_cast<Action>(actionOverrideX);
}
void
EventStateManager::WheelPrefs::GetMultiplierForDeltaXAndY(
const WidgetWheelEvent* aEvent,
Index aIndex,
double* aMultiplierForDeltaX,
double* aMultiplierForDeltaY)
{
// If the event should be treated as horizontal wheel operation, deltaY
// should be multiplied by mMultiplierY, however, it might be moved to
// deltaX for handling default action. In such case, we need to treat
// mMultiplierX and mMultiplierY as swapped.
*aMultiplierForDeltaX = mMultiplierX[aIndex];
*aMultiplierForDeltaY = mMultiplierY[aIndex];
if (aEvent->mDeltaValuesAdjustedForDefaultHandler &&
ComputeActionFor(aEvent) == ACTION_HORIZONTAL_SCROLL) {
std::swap(*aMultiplierForDeltaX, *aMultiplierForDeltaY);
}
}
void
EventStateManager::WheelPrefs::ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent)
{
@ -5780,16 +5809,19 @@ EventStateManager::WheelPrefs::ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent)
Index index = GetIndexFor(aEvent);
Init(index);
aEvent->mDeltaX *= mMultiplierX[index];
aEvent->mDeltaY *= mMultiplierY[index];
double multiplierForDeltaX = 1.0, multiplierForDeltaY = 1.0;
GetMultiplierForDeltaXAndY(aEvent, index,
&multiplierForDeltaX, &multiplierForDeltaY);
aEvent->mDeltaX *= multiplierForDeltaX;
aEvent->mDeltaY *= multiplierForDeltaY;
aEvent->mDeltaZ *= mMultiplierZ[index];
// If the multiplier is 1.0 or -1.0, i.e., it doesn't change the absolute
// value, we should use lineOrPageDelta values which were set by widget.
// Otherwise, we need to compute them from accumulated delta values.
if (!NeedToComputeLineOrPageDelta(aEvent)) {
aEvent->mLineOrPageDeltaX *= static_cast<int32_t>(mMultiplierX[index]);
aEvent->mLineOrPageDeltaY *= static_cast<int32_t>(mMultiplierY[index]);
aEvent->mLineOrPageDeltaX *= static_cast<int32_t>(multiplierForDeltaX);
aEvent->mLineOrPageDeltaY *= static_cast<int32_t>(multiplierForDeltaY);
} else {
aEvent->mLineOrPageDeltaX = 0;
aEvent->mLineOrPageDeltaY = 0;
@ -5813,16 +5845,19 @@ EventStateManager::WheelPrefs::CancelApplyingUserPrefsFromOverflowDelta(
// happy? Although, widget can know the pref applied delta values by
// referrencing the deltaX and deltaY of the event.
if (mMultiplierX[index]) {
aEvent->mOverflowDeltaX /= mMultiplierX[index];
double multiplierForDeltaX = 1.0, multiplierForDeltaY = 1.0;
GetMultiplierForDeltaXAndY(aEvent, index,
&multiplierForDeltaX, &multiplierForDeltaY);
if (multiplierForDeltaX) {
aEvent->mOverflowDeltaX /= multiplierForDeltaX;
}
if (mMultiplierY[index]) {
aEvent->mOverflowDeltaY /= mMultiplierY[index];
if (multiplierForDeltaY) {
aEvent->mOverflowDeltaY /= multiplierForDeltaY;
}
}
EventStateManager::WheelPrefs::Action
EventStateManager::WheelPrefs::ComputeActionFor(WidgetWheelEvent* aEvent)
EventStateManager::WheelPrefs::ComputeActionFor(const WidgetWheelEvent* aEvent)
{
Index index = GetIndexFor(aEvent);
Init(index);
@ -5831,7 +5866,9 @@ EventStateManager::WheelPrefs::ComputeActionFor(WidgetWheelEvent* aEvent)
(Abs(aEvent->mDeltaX) > Abs(aEvent->mDeltaY) &&
Abs(aEvent->mDeltaX) > Abs(aEvent->mDeltaZ));
Action* actions = deltaXPreferred ? mOverriddenActionsX : mActions;
if (actions[index] == ACTION_NONE || actions[index] == ACTION_SCROLL) {
if (actions[index] == ACTION_NONE ||
actions[index] == ACTION_SCROLL ||
actions[index] == ACTION_HORIZONTAL_SCROLL) {
return actions[index];
}
@ -5839,8 +5876,11 @@ EventStateManager::WheelPrefs::ComputeActionFor(WidgetWheelEvent* aEvent)
if (aEvent->mIsMomentum) {
// Use the default action. Note that user might kill the wheel scrolling.
Init(INDEX_DEFAULT);
return (actions[INDEX_DEFAULT] == ACTION_SCROLL) ? ACTION_SCROLL :
ACTION_NONE;
if (actions[INDEX_DEFAULT] == ACTION_SCROLL ||
actions[INDEX_DEFAULT] == ACTION_HORIZONTAL_SCROLL) {
return actions[INDEX_DEFAULT];
}
return ACTION_NONE;
}
return actions[index];
@ -5848,7 +5888,7 @@ EventStateManager::WheelPrefs::ComputeActionFor(WidgetWheelEvent* aEvent)
bool
EventStateManager::WheelPrefs::NeedToComputeLineOrPageDelta(
WidgetWheelEvent* aEvent)
const WidgetWheelEvent* aEvent)
{
Index index = GetIndexFor(aEvent);
Init(index);
@ -5858,15 +5898,19 @@ EventStateManager::WheelPrefs::NeedToComputeLineOrPageDelta(
}
void
EventStateManager::WheelPrefs::GetUserPrefsForEvent(WidgetWheelEvent* aEvent,
double* aOutMultiplierX,
double* aOutMultiplierY)
EventStateManager::WheelPrefs::GetUserPrefsForEvent(
const WidgetWheelEvent* aEvent,
double* aOutMultiplierX,
double* aOutMultiplierY)
{
Index index = GetIndexFor(aEvent);
Init(index);
*aOutMultiplierX = mMultiplierX[index];
*aOutMultiplierY = mMultiplierY[index];
double multiplierForDeltaX = 1.0, multiplierForDeltaY = 1.0;
GetMultiplierForDeltaXAndY(aEvent, index,
&multiplierForDeltaX, &multiplierForDeltaY);
*aOutMultiplierX = multiplierForDeltaX;
*aOutMultiplierY = multiplierForDeltaY;
}
// static
@ -5879,15 +5923,34 @@ EventStateManager::WheelPrefs::WheelEventsEnabledOnPlugins()
return sWheelEventsEnabledOnPlugins;
}
// static
bool
EventStateManager::WheelEventIsScrollAction(WidgetWheelEvent* aEvent)
EventStateManager::WheelEventIsScrollAction(const WidgetWheelEvent* aEvent)
{
return aEvent->mMessage == eWheel &&
WheelPrefs::GetInstance()->ComputeActionFor(aEvent) == WheelPrefs::ACTION_SCROLL;
if (aEvent->mMessage != eWheel) {
return false;
}
WheelPrefs::Action action =
WheelPrefs::GetInstance()->ComputeActionFor(aEvent);
return action == WheelPrefs::ACTION_SCROLL ||
action == WheelPrefs::ACTION_HORIZONTAL_SCROLL;
}
// static
bool
EventStateManager::WheelEventIsHorizontalScrollAction(
const WidgetWheelEvent* aEvent)
{
if (aEvent->mMessage != eWheel) {
return false;
}
WheelPrefs::Action action =
WheelPrefs::GetInstance()->ComputeActionFor(aEvent);
return action == WheelPrefs::ACTION_HORIZONTAL_SCROLL;
}
void
EventStateManager::GetUserPrefsForWheelEvent(WidgetWheelEvent* aEvent,
EventStateManager::GetUserPrefsForWheelEvent(const WidgetWheelEvent* aEvent,
double* aOutMultiplierX,
double* aOutMultiplierY)
{
@ -5897,7 +5960,7 @@ EventStateManager::GetUserPrefsForWheelEvent(WidgetWheelEvent* aEvent,
bool
EventStateManager::WheelPrefs::IsOverOnePageScrollAllowedX(
WidgetWheelEvent* aEvent)
const WidgetWheelEvent* aEvent)
{
Index index = GetIndexFor(aEvent);
Init(index);
@ -5907,7 +5970,7 @@ EventStateManager::WheelPrefs::IsOverOnePageScrollAllowedX(
bool
EventStateManager::WheelPrefs::IsOverOnePageScrollAllowedY(
WidgetWheelEvent* aEvent)
const WidgetWheelEvent* aEvent)
{
Index index = GetIndexFor(aEvent);
Init(index);

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

@ -304,10 +304,14 @@ public:
static bool IsRemoteTarget(nsIContent* aTarget);
// Returns true if the given WidgetWheelEvent will resolve to a scroll action.
static bool WheelEventIsScrollAction(WidgetWheelEvent* aEvent);
static bool WheelEventIsScrollAction(const WidgetWheelEvent* aEvent);
// Returns true if the given WidgetWheelEvent will resolve to a horizontal
// scroll action but it's a vertical wheel operation.
static bool WheelEventIsHorizontalScrollAction(const WidgetWheelEvent* aEvet);
// Returns user-set multipliers for a wheel event.
static void GetUserPrefsForWheelEvent(WidgetWheelEvent* aEvent,
static void GetUserPrefsForWheelEvent(const WidgetWheelEvent* aEvent,
double* aOutMultiplierX,
double* aOutMultiplierY);
@ -538,7 +542,7 @@ protected:
* Returns whether or not ApplyUserPrefsToDelta() would change the delta
* values of an event.
*/
void GetUserPrefsForEvent(WidgetWheelEvent* aEvent,
void GetUserPrefsForEvent(const WidgetWheelEvent* aEvent,
double* aOutMultiplierX,
double* aOutMultiplierY);
@ -558,25 +562,26 @@ protected:
ACTION_SCROLL,
ACTION_HISTORY,
ACTION_ZOOM,
ACTION_LAST = ACTION_ZOOM,
ACTION_HORIZONTAL_SCROLL,
ACTION_LAST = ACTION_HORIZONTAL_SCROLL,
// Following actions are used only by internal processing. So, cannot
// specified by prefs.
ACTION_SEND_TO_PLUGIN
ACTION_SEND_TO_PLUGIN,
};
Action ComputeActionFor(WidgetWheelEvent* aEvent);
Action ComputeActionFor(const WidgetWheelEvent* aEvent);
/**
* NeedToComputeLineOrPageDelta() returns if the aEvent needs to be
* computed the lineOrPageDelta values.
*/
bool NeedToComputeLineOrPageDelta(WidgetWheelEvent* aEvent);
bool NeedToComputeLineOrPageDelta(const WidgetWheelEvent* aEvent);
/**
* IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should
* be rounded down to the page width/height (false) or not (true).
*/
bool IsOverOnePageScrollAllowedX(WidgetWheelEvent* aEvent);
bool IsOverOnePageScrollAllowedY(WidgetWheelEvent* aEvent);
bool IsOverOnePageScrollAllowedX(const WidgetWheelEvent* aEvent);
bool IsOverOnePageScrollAllowedY(const WidgetWheelEvent* aEvent);
/**
* WheelEventsEnabledOnPlugins() returns true if user wants to use mouse
@ -609,7 +614,7 @@ protected:
* default index which is used at either no modifier key is pressed or
* two or modifier keys are pressed.
*/
Index GetIndexFor(WidgetWheelEvent* aEvent);
Index GetIndexFor(const WidgetWheelEvent* aEvent);
/**
* GetPrefNameBase() returns the base pref name for aEvent.
@ -625,6 +630,25 @@ protected:
void Reset();
/**
* Retrieve multiplier for aEvent->mDeltaX and aEvent->mDeltaY.
* If the default action is ACTION_HORIZONTAL_SCROLL and the delta values
* are adjusted by AutoWheelDeltaAdjuster(), this treats mMultiplierX as
* multiplier for deltaY and mMultiplierY as multiplier for deltaY.
*
* @param aEvent The event which is being handled.
* @param aIndex The index of mMultiplierX and mMultiplierY.
* Should be result of GetIndexFor(aEvent).
* @param aMultiplierForDeltaX Will be set to multiplier for
* aEvent->mDeltaX.
* @param aMultiplierForDeltaY Will be set to multiplier for
* aEvent->mDeltaY.
*/
void GetMultiplierForDeltaXAndY(const WidgetWheelEvent* aEvent,
Index aIndex,
double* aMultiplierForDeltaX,
double* aMultiplierForDeltaY);
bool mInit[COUNT_OF_MULTIPLIERS];
double mMultiplierX[COUNT_OF_MULTIPLIERS];
double mMultiplierY[COUNT_OF_MULTIPLIERS];

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

@ -529,8 +529,9 @@ ScrollbarsForWheel::DeactivateAllTemporarilyActivatedScrollTargets()
}
/******************************************************************/
/* mozilla::WheelTransaction */
/* mozilla::WheelTransaction::Prefs */
/******************************************************************/
int32_t WheelTransaction::Prefs::sMouseWheelAccelerationStart = -1;
int32_t WheelTransaction::Prefs::sMouseWheelAccelerationFactor = -1;
uint32_t WheelTransaction::Prefs::sMouseWheelTransactionTimeout = 1500;
@ -555,4 +556,47 @@ WheelTransaction::Prefs::InitializeStatics()
}
}
/******************************************************************/
/* mozilla::AutoWheelDeltaAdjuster */
/******************************************************************/
AutoWheelDeltaAdjuster::AutoWheelDeltaAdjuster(WidgetWheelEvent& aWheelEvent)
: mWheelEvent(aWheelEvent)
, mOldDeltaX(aWheelEvent.mDeltaX)
, mOldDeltaZ(aWheelEvent.mDeltaZ)
, mOldOverflowDeltaX(aWheelEvent.mOverflowDeltaX)
, mOldLineOrPageDeltaX(aWheelEvent.mLineOrPageDeltaX)
, mTreatedVerticalWheelAsHorizontalScroll(false)
{
MOZ_ASSERT(!aWheelEvent.mDeltaValuesAdjustedForDefaultHandler);
if (EventStateManager::WheelEventIsHorizontalScrollAction(&aWheelEvent)) {
// Move deltaY values to deltaX and set both deltaY and deltaZ to 0.
mWheelEvent.mDeltaX = mWheelEvent.mDeltaY;
mWheelEvent.mDeltaY = 0.0;
mWheelEvent.mDeltaZ = 0.0;
mWheelEvent.mOverflowDeltaX = mWheelEvent.mOverflowDeltaY;
mWheelEvent.mOverflowDeltaY = 0.0;
mWheelEvent.mLineOrPageDeltaX = mWheelEvent.mLineOrPageDeltaY;
mWheelEvent.mLineOrPageDeltaY = 0;
mWheelEvent.mDeltaValuesAdjustedForDefaultHandler = true;
mTreatedVerticalWheelAsHorizontalScroll = true;
}
}
AutoWheelDeltaAdjuster::~AutoWheelDeltaAdjuster()
{
if (mTreatedVerticalWheelAsHorizontalScroll &&
mWheelEvent.mDeltaValuesAdjustedForDefaultHandler) {
mWheelEvent.mDeltaY = mWheelEvent.mDeltaX;
mWheelEvent.mDeltaX = mOldDeltaX;
mWheelEvent.mDeltaZ = mOldDeltaZ;
mWheelEvent.mOverflowDeltaY = mWheelEvent.mOverflowDeltaX;
mWheelEvent.mOverflowDeltaX = mOldOverflowDeltaX;
mWheelEvent.mLineOrPageDeltaY = mWheelEvent.mLineOrPageDeltaX;
mWheelEvent.mLineOrPageDeltaX = mOldLineOrPageDeltaX;
mWheelEvent.mDeltaValuesAdjustedForDefaultHandler = false;
}
}
} // namespace mozilla

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

@ -204,6 +204,35 @@ protected:
};
};
/**
* When a wheel event should be treated as specially, e.g., it's a vertical
* wheel operation but user wants to scroll the target horizontally, this
* class adjust the delta values automatically. Then, restores the original
* value when the instance is destroyed.
*/
class MOZ_STACK_CLASS AutoWheelDeltaAdjuster final
{
public:
/**
* @param aWheelEvent A wheel event. The delta values may be
* modified for default handler.
* Its mDeltaValuesAdjustedForDefaultHandler
* must not be true because if it's true,
* the event has already been adjusted the
* delta values for default handler.
*/
explicit AutoWheelDeltaAdjuster(WidgetWheelEvent& aWheelEvent);
~AutoWheelDeltaAdjuster();
private:
WidgetWheelEvent& mWheelEvent;
double mOldDeltaX;
double mOldDeltaZ;
double mOldOverflowDeltaX;
int32_t mOldLineOrPageDeltaX;
bool mTreatedVerticalWheelAsHorizontalScroll;
};
} // namespace mozilla
#endif // mozilla_WheelHandlingHelper_h_

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

@ -36,6 +36,7 @@ EXPORTS.mozilla += [
'PhysicalKeyCodeNameList.h',
'TextComposition.h',
'VirtualKeyCodeList.h',
'WheelHandlingHelper.h',
]
EXPORTS.mozilla.dom += [

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

@ -78,6 +78,18 @@ var gScrollableElement = document.getElementById("scrollable");
var gScrolledElement = document.getElementById("scrolled");
var gSpacerForBodyElement = document.getElementById("spacerForBody");
const kDefaultActionNone = 0;
const kDefaultActionScroll = 1;
const kDefaultActionHistory = 2;
const kDefaultActionZoom = 3;
const kDefaultActionHorizontalScroll = 4;
const kDefaultActionOverrideXNoOverride = -1;
const kDefaultActionOverrideXNone = kDefaultActionNone;
const kDefaultActionOverrideXScroll = kDefaultActionScroll;
const kDefaultActionOverrideXHistory = kDefaultActionHistory;
const kDefaultActionOverrideXZoom = kDefaultActionZoom;
function is()
{
window.opener.is.apply(window.opener, arguments);
@ -538,98 +550,98 @@ function doTestScroll(aSettings, aCallback)
deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollDown },
{ description: "Scroll to bottom by momentum pixel scroll when lineOrPageDelta is 1, even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollDown },
{ description: "Scroll to top by momentum pixel scroll when lineOrPageDelta is 0, even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollUp },
{ description: "Scroll to top by momentum pixel scroll when lineOrPageDelta is -1, even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollUp },
{ description: "Scroll to right by momentum pixel scroll when lineOrPageDelta is 0, even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll to right by momentum pixel scroll when lineOrPageDelta is 1, even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll to left by momentum pixel scroll when lineOrPageDelta is 0, even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Scroll to left by momentum pixel scroll when lineOrPageDelta is -1, even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Scroll to bottom-right by momentum pixel scroll even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 8.0, deltaY: 8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollDown | kScrollRight },
{ description: "Scroll to bottom-left by momentum pixel scroll even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: -8.0, deltaY: 8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollDown | kScrollLeft },
{ description: "Scroll to top-left by momentum pixel scroll even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: -8.0, deltaY: -8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollUp | kScrollLeft },
{ description: "Scroll to top-right by momentum pixel scroll even if the action is history",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 8.0, deltaY: -8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kScrollUp | kScrollRight },
{ description: "Not Scroll by momentum pixel scroll for z (action is history)",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Not Scroll by momentum pixel scroll if default action is none (action is history)",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: true,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
shiftKey: false, ctrlKey: false, altKey: true, metaKey: false, osKey: false },
expected: kNoScroll,
prepare: function (cb) { SpecialPowers.pushPrefEnv({"set": [["mousewheel.default.action", 0]]}, cb); },
cleanup: function (cb) { SpecialPowers.pushPrefEnv({"set": [["mousewheel.default.action", 1]]}, cb); } },
@ -946,6 +958,350 @@ function doTestScroll(aSettings, aCallback)
doNextTest();
}
function doTestHorizontalScroll(aSettings, aCallback)
{
const kNoScroll = 0x00;
const kScrollLeft = 0x01;
const kScrollRight = 0x02;
const kTests = [
{ description: "Scroll to right by pixel scroll even if lineOrPageDelta is 0",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll to right by pixel scroll when lineOrPageDelta is 1",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 0.0, deltaY: 8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll to left by pixel scroll even if lineOrPageDelta is 0",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Scroll to left by pixel scroll when lineOrPageDelta is -1",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 0.0, deltaY: -8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Don't scroll by deltaX (pixel scroll, lineOrPageDelta is 0)",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Don't scroll by deltaX (pixel scroll, lineOrPageDelta is 1)",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 8.0, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Don't scroll by negative deltaX (pixel scroll, lineOrPageDelta is 0)",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Don't scroll by negative deltaX (pixel scroll, lineOrPageDelta is -1)",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: -8.0, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Scroll only to right by diagonal pixel scroll (to bottom-right)",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 8.0, deltaY: 8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll only to right by diagonal pixel scroll (to bottom-left)",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: -8.0, deltaY: 8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll only to left by diagonal pixel scroll (to top-left)",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: -8.0, deltaY: -8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Scroll only to left by pixel scroll (to bottom-right)",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 8.0, deltaY: -8.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Don't scroll by pixel scroll for z-axis",
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Scroll to right by line scroll even if lineOrPageDelta is 0",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll to right by line scroll when lineOrPageDelta is 1",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll to left by line scroll even if lineOrPageDelta is 0",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Scroll to left by line scroll when lineOrPageDelta is -1",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Don't scroll by deltaX (line scroll, lineOrPageDelta is 0)",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Don't scroll by deltaX (line scroll, lineOrPageDelta is 1)",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Don't scroll by negative deltaX (line scroll, lineOrPageDelta is 0)",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Don't scroll by negative deltaY (line scroll, lineOrPageDelta is -1)",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Scroll only to right by diagonal line scroll (to bottom-right)",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.5, deltaY: 0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll only to right by diagonal line scroll (to bottom-left)",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: -0.5, deltaY: 0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll only to left by diagonal line scroll (to top-left)",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: -0.5, deltaY: -0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Scroll only to left by line scroll (to top-right)",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.5, deltaY: -0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Don't scroll by line scroll for z-axis",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Scroll to right by page scroll even if lineOrPageDelta is 0",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll to right by page scroll when lineOrPageDelta is 1",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: 0.0, deltaY: 0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 1, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll to left by page scroll even if lineOrPageDelta is 0",
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Scroll to left by page scroll when lineOrPageDelta is -1",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: 0.0, deltaY: -0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: -1, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Don't scroll by deltaX (page scroll, lineOrPageDelta is 0)",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Don't scroll by deltaX (page scroll, lineOrPageDelta is 1)",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: 0.5, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Don't scroll by deltaX (page scroll, lineOrPageDelta is 0)",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Don't scroll by deltaX (page scroll, lineOrPageDelta is -1)",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: -0.5, deltaY: 0.0, deltaZ: 0.0,
lineOrPageDeltaX: -1, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
{ description: "Scroll only to right by diagonal page scroll (to bottom-right)",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: 0.5, deltaY: 0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll only to right by diagonal page scroll (to bottom-left)",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: -0.5, deltaY: 0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollRight },
{ description: "Scroll only to left by diagonal page scroll (to top-left)",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: -0.5, deltaY: -0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Scroll only to left by diagonal page scroll (to top-right)",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: 0.5, deltaY: -0.5, deltaZ: 0.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kScrollLeft },
{ description: "Don't scroll by page scroll for z-axis",
event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: 0.0, deltaY: 0.0, deltaZ: 1.0,
lineOrPageDeltaX: 0, lineOrPageDeltaY: 0, isMomentum: false,
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
expected: kNoScroll },
];
var description;
var currentTestIndex = -1;
// deltaY should cause horizontal scroll and affected by deltaMultiplierY.
// So, horizontal scroll amount and direction is affected by deltaMultiplierY.
var isXReverted = (aSettings.deltaMultiplierY < 0);
function doNextTest()
{
if (++currentTestIndex >= kTests.length) {
SimpleTest.executeSoon(aCallback);
return;
}
gScrollableElement.scrollTop = 1000;
gScrollableElement.scrollLeft = 1000;
var currentTest = kTests[currentTestIndex];
description = "doTestHorizontalScroll(aSettings=" + aSettings.description + "), " + currentTest.description + ": ";
if (currentTest.prepare) {
currentTest.prepare(doTestCurrentScroll);
} else {
doTestCurrentScroll();
}
}
function doTestCurrentScroll() {
var currentTest = kTests[currentTestIndex];
sendWheelAndWait(10, 10, currentTest.event, function () {
is(gScrollableElement.scrollTop, 1000, description + "scrolled vertical");
if (currentTest.expected == kNoScroll) {
is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
} else {
var scrollLeft = !isXReverted ? (currentTest.expected & kScrollLeft) :
(currentTest.expected & kScrollRight);
var scrollRight = !isXReverted ? (currentTest.expected & kScrollRight) :
(currentTest.expected & kScrollLeft);
if (scrollLeft) {
ok(gScrollableElement.scrollLeft < 1000, description + "not scrolled to left, got " + gScrollableElement.scrollLeft);
} else if (scrollRight) {
ok(gScrollableElement.scrollLeft > 1000, description + "not scrolled to right, got " + gScrollableElement.scrollLeft);
} else {
is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
}
}
if (currentTest.cleanup) {
currentTest.cleanup(nextStep);
} else {
nextStep();
}
function nextStep() {
winUtils.advanceTimeAndRefresh(100);
doNextTest();
}
});
}
doNextTest();
}
function doTestZoom(aSettings, aCallback)
{
if ((aSettings.deltaMultiplierX != 1.0 && aSettings.deltaMultiplierX != -1.0) ||
@ -1659,109 +2015,109 @@ function doTestActionOverride(aCallback)
const kScrollRight = 0x08;
const kTests = [
{ action: 1, override_x: -1,
{ action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNoOverride,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kScrollDown | kScrollRight
},
{ action: 1, override_x: 0,
{ action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNone,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kScrollDown | kScrollRight
},
{ action: 1, override_x: 1,
{ action: kDefaultActionScroll, override_x: kDefaultActionOverrideXScroll,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kScrollDown | kScrollRight
},
{ action: 0, override_x: -1,
{ action: kDefaultActionNone, override_x: kDefaultActionOverrideXNoOverride,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kNoScroll
},
{ action: 0, override_x: 0,
{ action: kDefaultActionNone, override_x: kDefaultActionOverrideXNone,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kNoScroll
},
{ action: 0, override_x: 1,
{ action: kDefaultActionNone, override_x: kDefaultActionOverrideXScroll,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kNoScroll
},
{ action: 1, override_x: -1,
{ action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNoOverride,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 0.5,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kScrollDown | kScrollRight
},
{ action: 1, override_x: 0,
{ action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNone,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 0.5,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kNoScroll
},
{ action: 1, override_x: 1,
{ action: kDefaultActionScroll, override_x: kDefaultActionOverrideXScroll,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 0.5,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kScrollDown | kScrollRight
},
{ action: 0, override_x: -1,
{ action: kDefaultActionNone, override_x: kDefaultActionOverrideXNoOverride,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 0.5,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kNoScroll
},
{ action: 0, override_x: 0,
{ action: kDefaultActionNone, override_x: kDefaultActionOverrideXNone,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 0.5,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kNoScroll
},
{ action: 0, override_x: 1,
{ action: kDefaultActionNone, override_x: kDefaultActionOverrideXScroll,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 0.5,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kScrollDown | kScrollRight
},
{ action: 1, override_x: -1,
{ action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNoOverride,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.5, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kScrollDown | kScrollRight
},
{ action: 1, override_x: 0,
{ action: kDefaultActionScroll, override_x: kDefaultActionOverrideXNone,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.5, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kScrollDown | kScrollRight
},
{ action: 1, override_x: 1,
{ action: kDefaultActionScroll, override_x: kDefaultActionOverrideXScroll,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.5, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kScrollDown | kScrollRight
},
{ action: 0, override_x: -1,
{ action: kDefaultActionNone, override_x: kDefaultActionOverrideXNoOverride,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.5, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kNoScroll
},
{ action: 0, override_x: 0,
{ action: kDefaultActionNone, override_x: kDefaultActionOverrideXNone,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.5, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
expected: kNoScroll
},
{ action: 0, override_x: 1,
{ action: kDefaultActionNone, override_x: kDefaultActionOverrideXScroll,
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 0.5, deltaY: 1.0,
lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 },
@ -1820,12 +2176,14 @@ function runTests()
SpecialPowers.pushPrefEnv({"set": [
["test.events.async.enabled", true],
["general.smoothScroll", false],
["mousewheel.default.action", 1], // scroll
["mousewheel.default.action.override_x", -1],
["mousewheel.with_shift.action", 2], // history
["mousewheel.with_shift.action.override_x", -1],
["mousewheel.with_control.action", 3], // zoom
["mousewheel.with_control.action.override_x", -1]]},
["mousewheel.default.action", kDefaultActionScroll],
["mousewheel.default.action.override_x", kDefaultActionOverrideXNoOverride],
["mousewheel.with_shift.action", kDefaultActionHorizontalScroll],
["mousewheel.with_shift.action.override_x", kDefaultActionOverrideXNoOverride],
["mousewheel.with_control.action", kDefaultActionZoom],
["mousewheel.with_control.action.override_x", kDefaultActionOverrideXNoOverride],
["mousewheel.with_alt.action", kDefaultActionHistory],
["mousewheel.with_alt.action.override_x", kDefaultActionOverrideXNoOverride]]},
runTests2);
}
@ -1859,20 +2217,22 @@ function runTests2()
function doTest() {
setDeltaMultiplierSettings(kSettings[index], function () {
doTestScroll(kSettings[index], function () {
doTestZoom(kSettings[index], function() {
if (++index == kSettings.length) {
setDeltaMultiplierSettings(kSettings[0], function() {
doTestZoomedScroll(function() {
doTestWholeScroll(function() {
doTestActionOverride(function() {
finishTests();
doTestHorizontalScroll(kSettings[index], function() {
doTestZoom(kSettings[index], function() {
if (++index == kSettings.length) {
setDeltaMultiplierSettings(kSettings[0], function() {
doTestZoomedScroll(function() {
doTestWholeScroll(function() {
doTestActionOverride(function() {
finishTests();
});
});
});
});
});
} else {
doTest();
}
} else {
doTest();
}
});
});
});
});

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

@ -13,6 +13,7 @@
#include "mozilla/MouseEvents.h" // for WidgetMouseEvent
#include "mozilla/TextEvents.h" // for WidgetKeyboardEvent
#include "mozilla/TouchEvents.h" // for WidgetTouchEvent
#include "mozilla/WheelHandlingHelper.h" // for AutoWheelDeltaAdjuster
namespace mozilla {
namespace layers {
@ -113,31 +114,39 @@ IAPZCTreeManager::ReceiveInputEvent(
scrollMode = ScrollWheelInput::SCROLLMODE_SMOOTH;
}
ScreenPoint origin(wheelEvent.mRefPoint.x, wheelEvent.mRefPoint.y);
ScrollWheelInput input(wheelEvent.mTime, wheelEvent.mTimeStamp, 0,
scrollMode,
ScrollWheelInput::DeltaTypeForDeltaMode(
wheelEvent.mDeltaMode),
origin,
wheelEvent.mDeltaX, wheelEvent.mDeltaY,
wheelEvent.mAllowToOverrideSystemScrollSpeed);
// AutoWheelDeltaAdjuster may adjust the delta values for default
// action hander. The delta values will be restored automatically
// when its instance is destroyed.
AutoWheelDeltaAdjuster adjuster(wheelEvent);
// We add the user multiplier as a separate field, rather than premultiplying
// it, because if the input is converted back to a WidgetWheelEvent, then
// EventStateManager would apply the delta a second time. We could in theory
// work around this by asking ESM to customize the event much sooner, and
// then save the "mCustomizedByUserPrefs" bit on ScrollWheelInput - but for
// now, this seems easier.
EventStateManager::GetUserPrefsForWheelEvent(&wheelEvent,
&input.mUserDeltaMultiplierX,
&input.mUserDeltaMultiplierY);
// If the wheel event becomes no-op event, don't handle it as scroll.
if (wheelEvent.mDeltaX || wheelEvent.mDeltaY) {
ScreenPoint origin(wheelEvent.mRefPoint.x, wheelEvent.mRefPoint.y);
ScrollWheelInput input(wheelEvent.mTime, wheelEvent.mTimeStamp, 0,
scrollMode,
ScrollWheelInput::DeltaTypeForDeltaMode(
wheelEvent.mDeltaMode),
origin,
wheelEvent.mDeltaX, wheelEvent.mDeltaY,
wheelEvent.mAllowToOverrideSystemScrollSpeed);
nsEventStatus status = ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId);
wheelEvent.mRefPoint.x = input.mOrigin.x;
wheelEvent.mRefPoint.y = input.mOrigin.y;
wheelEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
wheelEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
return status;
// We add the user multiplier as a separate field, rather than premultiplying
// it, because if the input is converted back to a WidgetWheelEvent, then
// EventStateManager would apply the delta a second time. We could in theory
// work around this by asking ESM to customize the event much sooner, and
// then save the "mCustomizedByUserPrefs" bit on ScrollWheelInput - but for
// now, this seems easier.
EventStateManager::GetUserPrefsForWheelEvent(&wheelEvent,
&input.mUserDeltaMultiplierX,
&input.mUserDeltaMultiplierY);
nsEventStatus status = ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId);
wheelEvent.mRefPoint.x = input.mOrigin.x;
wheelEvent.mRefPoint.y = input.mOrigin.y;
wheelEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
wheelEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
return status;
}
}
UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage);

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

@ -2731,17 +2731,23 @@ pref("mousewheel.system_scroll_override_on_root_content.horizontal.factor", 200)
// 1: Scrolling contents
// 2: Go back or go forward, in your history
// 3: Zoom in or out.
// 4: Treat vertical wheel as horizontal scroll
// This treats vertical wheel operation (i.e., deltaY) as horizontal
// scroll. deltaX and deltaZ are always ignored. So, only
// "delta_multiplier_y" pref affects the scroll speed.
pref("mousewheel.default.action", 1);
pref("mousewheel.with_alt.action", 2);
pref("mousewheel.with_control.action", 3);
pref("mousewheel.with_meta.action", 1); // command key on Mac
pref("mousewheel.with_shift.action", 1);
pref("mousewheel.with_shift.action", 4);
pref("mousewheel.with_win.action", 1);
// mousewheel.*.action.override_x will override the action
// when the mouse wheel is rotated along the x direction.
// -1: Don't override the action.
// 0 to 3: Override the action with the specified value.
// Note that 4 isn't available because it doesn't make sense to apply the
// default action only for y direction to this pref.
pref("mousewheel.default.action.override_x", -1);
pref("mousewheel.with_alt.action.override_x", -1);
pref("mousewheel.with_control.action.override_x", -1);

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

@ -490,6 +490,7 @@ private:
, mViewPortIsOverscrolled(false)
, mCanTriggerSwipe(false)
, mAllowToOverrideSystemScrollSpeed(false)
, mDeltaValuesAdjustedForDefaultHandler(false)
{
}
@ -514,6 +515,7 @@ public:
, mViewPortIsOverscrolled(false)
, mCanTriggerSwipe(false)
, mAllowToOverrideSystemScrollSpeed(true)
, mDeltaValuesAdjustedForDefaultHandler(false)
{
}
@ -631,6 +633,10 @@ public:
// it's enabled by the pref.
bool mAllowToOverrideSystemScrollSpeed;
// While default handler handles a wheel event specially (e.g., treating
// mDeltaY as horizontal scroll), this is set to true.
bool mDeltaValuesAdjustedForDefaultHandler;
void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets)
{
AssignMouseEventBaseData(aEvent, aCopyTargets);
@ -652,6 +658,8 @@ public:
mCanTriggerSwipe = aEvent.mCanTriggerSwipe;
mAllowToOverrideSystemScrollSpeed =
aEvent.mAllowToOverrideSystemScrollSpeed;
mDeltaValuesAdjustedForDefaultHandler =
aEvent.mDeltaValuesAdjustedForDefaultHandler;
}
// System scroll speed settings may be too slow at using Gecko. In such

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

@ -199,6 +199,7 @@ struct ParamTraits<mozilla::WidgetWheelEvent>
WriteParam(aMsg, aParam.mViewPortIsOverscrolled);
WriteParam(aMsg, aParam.mCanTriggerSwipe);
WriteParam(aMsg, aParam.mAllowToOverrideSystemScrollSpeed);
WriteParam(aMsg, aParam.mDeltaValuesAdjustedForDefaultHandler);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
@ -222,7 +223,8 @@ struct ParamTraits<mozilla::WidgetWheelEvent>
ReadParam(aMsg, aIter, &aResult->mOverflowDeltaY) &&
ReadParam(aMsg, aIter, &aResult->mViewPortIsOverscrolled) &&
ReadParam(aMsg, aIter, &aResult->mCanTriggerSwipe) &&
ReadParam(aMsg, aIter, &aResult->mAllowToOverrideSystemScrollSpeed);
ReadParam(aMsg, aIter, &aResult->mAllowToOverrideSystemScrollSpeed) &&
ReadParam(aMsg, aIter, &aResult->mDeltaValuesAdjustedForDefaultHandler);
aResult->mScrollType =
static_cast<mozilla::WidgetWheelEvent::ScrollType>(scrollType);
return rv;