Bug 786120 - Implement mousewheel.*.action.override_x. r=smaug
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Sat, 08 Dec 2012 13:08:19 +0900
changeset 115411 15cf1f943bc9
parent 115410 a285d038f2c3
child 115412 89dca2ab7d86
push id24003
push usereakhgari@mozilla.com
push dateSun, 09 Dec 2012 18:17:18 +0000
treeherdermozilla-central@725eb8792d27 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs786120
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 786120 - Implement mousewheel.*.action.override_x. r=smaug
content/events/src/nsEventStateManager.cpp
content/events/src/nsEventStateManager.h
content/events/test/window_wheel_default_action.html
modules/libpref/src/init/all.js
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -5452,23 +5452,35 @@ nsEventStateManager::WheelPrefs::Init(
 
   nsAutoCString prefNameZ(basePrefName);
   prefNameZ.AppendLiteral("delta_multiplier_z");
   mMultiplierZ[aIndex] =
     static_cast<double>(Preferences::GetInt(prefNameZ.get(), 100)) / 100;
 
   nsAutoCString prefNameAction(basePrefName);
   prefNameAction.AppendLiteral("action");
-  mActions[aIndex] =
-    static_cast<Action>(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>(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>(action)
+                              : static_cast<Action>(actionOverrideX);
 }
 
 void
 nsEventStateManager::WheelPrefs::ApplyUserPrefsToDelta(
                                    widget::WheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
@@ -5519,31 +5531,35 @@ nsEventStateManager::WheelPrefs::Compute
 {
   if (!aEvent->deltaX && !aEvent->deltaY) {
     return ACTION_NONE;
   }
 
   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
 nsEventStateManager::WheelPrefs::NeedToComputeLineOrPageDelta(
                                    widget::WheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -345,17 +345,17 @@ protected:
      * CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation.
      */
     void CancelApplyingUserPrefsFromOverflowDelta(
                                     mozilla::widget::WheelEvent* aEvent);
 
     /**
      * Computes the default action for the aEvent with the prefs.
      */
-    enum Action
+    enum Action MOZ_ENUM_TYPE(uint8_t)
     {
       ACTION_NONE = 0,
       ACTION_SCROLL,
       ACTION_HISTORY,
       ACTION_ZOOM,
       ACTION_LAST = ACTION_ZOOM
     };
     Action ComputeActionFor(mozilla::widget::WheelEvent* aEvent);
@@ -423,16 +423,22 @@ protected:
       MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL = 1000
     };
 
     bool mInit[COUNT_OF_MULTIPLIERS];
     double mMultiplierX[COUNT_OF_MULTIPLIERS];
     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;
   };
 
   /**
    * DeltaDirection is used for specifying whether the called method should
    * handle vertical delta or horizontal delta.
    * This is clearer than using bool.
--- a/content/events/test/window_wheel_default_action.html
+++ b/content/events/test/window_wheel_default_action.html
@@ -1526,16 +1526,176 @@ function doTestWholeScroll(aCallback)
       } else {
         doIt();
       }
     }, 20);
   }
   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);
 
   SpecialPowers.setIntPref("mousewheel.default.action", 1);      // scroll
   SpecialPowers.setIntPref("mousewheel.with_shift.action", 2);   // history
   SpecialPowers.setIntPref("mousewheel.with_control.action", 3); // zoom
 
@@ -1562,29 +1722,31 @@ function runTests()
       deltaMultiplierX:  1.0, deltaMultiplierY:  1.0, deltaMultiplierZ: -2.0 },
   ];
 
   var index = 0;
 
   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();
 }
 
 function finishTests()
 {
   SpecialPowers.clearUserPref("general.smoothScroll");
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1440,16 +1440,27 @@ pref("mousewheel.system_scroll_override_
 // 3: Zoom in or out.
 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_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
 // reverted.  The absolue value must be 100 or larger.
 pref("mousewheel.default.delta_multiplier_x", 100);
 pref("mousewheel.default.delta_multiplier_y", 100);
 pref("mousewheel.default.delta_multiplier_z", 100);
 pref("mousewheel.with_alt.delta_multiplier_x", 100);