From 1e56bc30a5d0e5c0c88e52f5b8deabee90192d58 Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Sat, 8 Dec 2012 13:08:19 +0900 Subject: [PATCH] Bug 786120 - Implement mousewheel.*.action.override_x. r=smaug --- content/events/src/nsEventStateManager.cpp | 36 +++- content/events/src/nsEventStateManager.h | 8 +- .../test/window_wheel_default_action.html | 180 +++++++++++++++++- modules/libpref/src/init/all.js | 11 ++ 4 files changed, 215 insertions(+), 20 deletions(-) diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 644cb5f02a5b..0ddd23e3ba25 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -5457,13 +5457,25 @@ nsEventStateManager::WheelPrefs::Init( nsAutoCString prefNameAction(basePrefName); prefNameAction.AppendLiteral("action"); - mActions[aIndex] = - static_cast(Preferences::GetInt(prefNameAction.get(), - ACTION_SCROLL)); - if (mActions[aIndex] < ACTION_NONE || mActions[aIndex] > ACTION_LAST) { + int32_t action = Preferences::GetInt(prefNameAction.get(), ACTION_SCROLL); + if (action < ACTION_NONE || action > ACTION_LAST) { NS_WARNING("Unsupported action pref value, replaced with 'Scroll'."); - mActions[aIndex] = ACTION_SCROLL; + action = ACTION_SCROLL; } + mActions[aIndex] = static_cast(action); + + // 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. + prefNameAction.AppendLiteral(".override_x"); + int32_t actionOverrideX = Preferences::GetInt(prefNameAction.get(), -1); + if (actionOverrideX < -1 || actionOverrideX > ACTION_LAST) { + NS_WARNING("Unsupported action override pref value, didn't override."); + actionOverrideX = -1; + } + mOverriddenActionsX[aIndex] = (actionOverrideX == -1) + ? static_cast(action) + : static_cast(actionOverrideX); } void @@ -5524,21 +5536,25 @@ nsEventStateManager::WheelPrefs::ComputeActionFor(widget::WheelEvent* aEvent) Index index = GetIndexFor(aEvent); Init(index); - if (mActions[index] == ACTION_NONE || mActions[index] == ACTION_SCROLL) { - return mActions[index]; + bool deltaXPreferred = + (std::abs(aEvent->deltaX) > std::abs(aEvent->deltaY) && + std::abs(aEvent->deltaX) > std::abs(aEvent->deltaZ)); + Action* actions = deltaXPreferred ? mOverriddenActionsX : mActions; + if (actions[index] == ACTION_NONE || actions[index] == ACTION_SCROLL) { + return actions[index]; } // Momentum events shouldn't run special actions. if (aEvent->isMomentum) { // Use the default action. Note that user might kill the wheel scrolling. Init(INDEX_DEFAULT); - return (mActions[INDEX_DEFAULT] == ACTION_SCROLL) ? ACTION_SCROLL : - ACTION_NONE; + return (actions[INDEX_DEFAULT] == ACTION_SCROLL) ? ACTION_SCROLL : + ACTION_NONE; } // If this event doesn't cause NS_MOUSE_SCROLL event or the direction is // oblique, history and zoom shouldn't be executed. - return !aEvent->GetPreferredIntDelta() ? ACTION_NONE : mActions[index]; + return !aEvent->GetPreferredIntDelta() ? ACTION_NONE : actions[index]; } bool diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h index b3d0e3c568b6..0ce6a01bf7ca 100644 --- a/content/events/src/nsEventStateManager.h +++ b/content/events/src/nsEventStateManager.h @@ -350,7 +350,7 @@ protected: /** * Computes the default action for the aEvent with the prefs. */ - enum Action + enum Action MOZ_ENUM_TYPE(uint8_t) { ACTION_NONE = 0, ACTION_SCROLL, @@ -428,6 +428,12 @@ protected: double mMultiplierY[COUNT_OF_MULTIPLIERS]; double mMultiplierZ[COUNT_OF_MULTIPLIERS]; Action mActions[COUNT_OF_MULTIPLIERS]; + /** + * action values overridden by .override_x pref. + * If an .override_x value is -1, same as the + * corresponding mActions value. + */ + Action mOverriddenActionsX[COUNT_OF_MULTIPLIERS]; static WheelPrefs* sInstance; }; diff --git a/content/events/test/window_wheel_default_action.html b/content/events/test/window_wheel_default_action.html index bd3f8e082f05..b98532961079 100644 --- a/content/events/test/window_wheel_default_action.html +++ b/content/events/test/window_wheel_default_action.html @@ -1531,6 +1531,166 @@ function doTestWholeScroll(aCallback) doIt(); } +function doTestActionOverride(aCallback) +{ + const kNoScroll = 0x00; + const kScrollUp = 0x01; + const kScrollDown = 0x02; + const kScrollLeft = 0x04; + const kScrollRight = 0x08; + + const kTests = [ + { action: 1, override_x: -1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kScrollDown | kScrollRight + }, + { action: 1, override_x: 0, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kScrollDown | kScrollRight + }, + { action: 1, override_x: 1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kScrollDown | kScrollRight + }, + { action: 0, override_x: -1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kNoScroll + }, + { action: 0, override_x: 0, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kNoScroll + }, + { action: 0, override_x: 1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kNoScroll + }, + { action: 1, override_x: -1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 0.5, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kScrollDown | kScrollRight + }, + { action: 1, override_x: 0, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 0.5, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kNoScroll + }, + { action: 1, override_x: 1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 0.5, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kScrollDown | kScrollRight + }, + { action: 0, override_x: -1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 0.5, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kNoScroll + }, + { action: 0, override_x: 0, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 0.5, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kNoScroll + }, + { action: 0, override_x: 1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 1.0, deltaY: 0.5, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kScrollDown | kScrollRight + }, + { action: 1, override_x: -1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 0.5, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kScrollDown | kScrollRight + }, + { action: 1, override_x: 0, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 0.5, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kScrollDown | kScrollRight + }, + { action: 1, override_x: 1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 0.5, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kScrollDown | kScrollRight + }, + { action: 0, override_x: -1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 0.5, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kNoScroll + }, + { action: 0, override_x: 0, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 0.5, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kNoScroll + }, + { action: 0, override_x: 1, + event: { deltaMode: WheelEvent.DOM_DELTA_LINE, + deltaX: 0.5, deltaY: 1.0, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }, + expected: kNoScroll + }, + ]; + + var index = 0; + + function doIt() + { + const kTest = kTests[index]; + description = "doTestActionOverride(action=" + kTest.action + ", " + + "override_x=" + kTest.override_x + ", " + + "deltaX=" + kTest.event.deltaX + ", " + + "deltaY=" + kTest.event.deltaY + "): "; + SpecialPowers.setIntPref("mousewheel.default.action", kTest.action); + SpecialPowers.setIntPref("mousewheel.default.action.override_x", kTest.override_x); + gScrollableElement.scrollTop = 1000; + gScrollableElement.scrollLeft = 1000; + synthesizeWheel(gScrollableElement, 10, 10, kTest.event); + hitEventLoop(function () { + if (kTest.expected & kScrollUp) { + ok(gScrollableElement.scrollTop < 1000, description + "not scrolled up, got " + gScrollableElement.scrollTop); + } else if (kTest.expected & kScrollDown) { + ok(gScrollableElement.scrollTop > 1000, description + "not scrolled down, got " + gScrollableElement.scrollTop); + } else { + is(gScrollableElement.scrollTop, 1000, description + "scrolled vertical"); + } + if (kTest.expected & kScrollLeft) { + ok(gScrollableElement.scrollLeft < 1000, description + "not scrolled to left, got " + gScrollableElement.scrollLeft); + } else if (kTest.expected & kScrollRight) { + ok(gScrollableElement.scrollLeft > 1000, description + "not scrolled to right, got " + gScrollableElement.scrollLeft); + } else { + is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal"); + } + if (++index == kTests.length) { + SpecialPowers.setIntPref("mousewheel.default.action", 1); + SpecialPowers.clearUserPref("mousewheel.default.action.override_x"); + SimpleTest.executeSoon(aCallback); + } else { + doIt(); + } + }, 20); + } + doIt(); +} + function runTests() { SpecialPowers.setBoolPref("general.smoothScroll", false); @@ -1567,19 +1727,21 @@ function runTests() function doTest() { setDeltaMultiplierSettings(kSettings[index]); doTestScroll(kSettings[index], function () { - doTestZoom(kSettings[index], function() { - if (++index == kSettings.length) { - setDeltaMultiplierSettings(kSettings[0]); - doTestZoomedScroll(function() { - doTestWholeScroll(function() { + doTestZoom(kSettings[index], function() { + if (++index == kSettings.length) { + setDeltaMultiplierSettings(kSettings[0]); + doTestZoomedScroll(function() { + doTestWholeScroll(function() { + doTestActionOverride(function() { finishTests(); }); }); - } else { - doTest(); - } - }); + }); + } else { + doTest(); + } }); + }); } doTest(); } diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index de33d09a20d0..2924afe9ffae 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -1445,6 +1445,17 @@ pref("mousewheel.with_meta.action", 1); // command key on Mac pref("mousewheel.with_shift.action", 1); 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. +pref("mousewheel.default.action.override_x", -1); +pref("mousewheel.with_alt.action.override_x", -1); +pref("mousewheel.with_control.action.override_x", -1); +pref("mousewheel.with_meta.action.override_x", -1); // command key on Mac +pref("mousewheel.with_shift.action.override_x", -1); +pref("mousewheel.with_win.action.override_x", -1); + // mousewheel.*.delta_multiplier_* can specify the value muliplied by the delta // value. The values will be used after divided by 100. I.e., 100 means 1.0, // -100 means -1.0. If the values were negative, the direction would be