Bug 501608 - menu popup sounds are played when showing the autoscrolling popup. r=enn
☠☠ backed out by 1708ccd0ffe4 ☠ ☠
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 31 Jul 2009 07:23:51 +0200
changeset 30962 8cd49a8cbb88c1316079b79b7a10b5b135fb4e9a
parent 30961 225d454e390336d1cadb07d9196e7f8520528ca9
child 30963 6a5f22ccbe0e8ec06f11568a2d8a58d42d60d088
child 30980 1708ccd0ffe4a65523cadc76d5e94c1f83cbd5ba
push idunknown
push userunknown
push dateunknown
reviewersenn
bugs501608
milestone1.9.2a1pre
Bug 501608 - menu popup sounds are played when showing the autoscrolling popup. r=enn
toolkit/content/tests/browser/Makefile.in
toolkit/content/tests/browser/browser_keyevents_during_autoscrolling.js
toolkit/content/widgets/browser.xml
--- a/toolkit/content/tests/browser/Makefile.in
+++ b/toolkit/content/tests/browser/Makefile.in
@@ -45,10 +45,16 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_FILES = \
   bug471962_testpage_inner.sjs \
   bug471962_testpage_outer.sjs \
   browser_bug471962.js \
   $(NULL)
 
+# browser_keyevents_during_autoscrolling.js cannot start the autoscrolling by
+# synthesizeMouse with middle button on linux, therefore, disable it temporarily
+ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)
+_BROWSER_FILES += browser_keyevents_during_autoscrolling.js
+endif
+
 libs:: $(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/browser/browser_keyevents_during_autoscrolling.js
@@ -0,0 +1,118 @@
+function test()
+{
+  const kPrefName_AutoScroll = "general.autoScroll";
+  const kPrefName_ContentLoadURL = "middlemouse.contentLoadURL";
+  var prefSvc = Components.classes["@mozilla.org/preferences-service;1"]
+                          .getService(Components.interfaces.nsIPrefBranch2);
+  var kAutoScrollingEnabled = prefSvc.getBoolPref(kPrefName_AutoScroll);
+  prefSvc.setBoolPref(kPrefName_AutoScroll, true);
+
+  const kNoKeyEvents   = 0;
+  const kKeyDownEvent  = 1;
+  const kKeyPressEvent = 2;
+  const kKeyUpEvent    = 4;
+  const kAllKeyEvents  = 7;
+
+  var expectedKeyEvents;
+  var dispatchedKeyEvents;
+  var key;
+  var root;
+
+  function sendKey(aKey)
+  {
+    key = aKey;
+    dispatchedKeyEvents = kNoKeyEvents;
+    EventUtils.synthesizeKey(key, {}, gBrowser.contentWindow);
+    is(dispatchedKeyEvents, expectedKeyEvents,
+       "unexpected key events were dispatched or not dispatched: " + key);
+  }
+
+  function onKey(aEvent)
+  {
+    if (aEvent.target != root) {
+      ok(false, "unknown target: " + aEvent.target.tagName);
+      return;
+    }
+
+    var keyFlag;
+    switch (aEvent.type) {
+      case "keydown":
+        keyFlag = kKeyDownEvent;
+        break;
+      case "keypress":
+        keyFlag = kKeyPressEvent;
+        break;
+      case "keyup":
+        keyFlag = kKeyUpEvent;
+        break;
+      default:
+        ok(false, "Unknown events: " + aEvent.type);
+        return;
+    }
+    dispatchedKeyEvents |= keyFlag;
+    is(keyFlag, expectedKeyEvents & keyFlag, aEvent.type + " fired: " + key);
+  }
+
+  function startTest() {
+    waitForExplicitFinish();
+    gBrowser.addEventListener("load", onLoad, false);
+    var dataUri = 'data:text/html,<body style="height:10000px;"></body>';
+    gBrowser.loadURI(dataUri);
+  }
+
+  function onLoad() {
+    gBrowser.removeEventListener("load", onLoad, false);
+
+    gBrowser.contentWindow.focus();
+
+    var doc = gBrowser.contentDocument;
+
+    root = doc.documentElement;
+    root.addEventListener("keydown", onKey, true);
+    root.addEventListener("keypress", onKey, true);
+    root.addEventListener("keyup", onKey, true);
+
+    // Test whether the key events are handled correctly under normal condition
+    expectedKeyEvents = kAllKeyEvents;
+    sendKey("A");
+
+    // Start autoscrolling by middle button lick on the page
+    EventUtils.synthesizeMouse(root, 10, 10, { button: 1 },
+                               gBrowser.contentWindow);
+
+    // Most key events should be eaten by the browser.
+    expectedKeyEvents = kNoKeyEvents;
+    sendKey("A");
+    sendKey("VK_DOWN");
+    sendKey("VK_RETURN");
+    sendKey("VK_ENTER");
+    sendKey("VK_HOME");
+    sendKey("VK_END");
+    sendKey("VK_TAB");
+    sendKey("VK_ENTER");
+
+    // Finish autoscrolling by ESC key.  Note that only keydown and keypress
+    // events are eaten because keyup event is fired *after* the autoscrolling
+    // is finished.
+    expectedKeyEvents = kKeyUpEvent;
+    sendKey("VK_ESCAPE");
+
+    // Test whether the key events are handled correctly under normal condition
+    expectedKeyEvents = kAllKeyEvents;
+    sendKey("A");
+
+    root.removeEventListener("keydown", onKey, true);
+    root.removeEventListener("keypress", onKey, true);
+    root.removeEventListener("keyup", onKey, true);
+
+    // restore the changed prefs
+    prefSvc.setBoolPref(kPrefName_AutoScroll, kAutoScrollingEnabled);
+
+    // cleaning-up
+    gBrowser.loadURI("about:blank");
+
+    finish();
+  }
+
+  startTest();
+}
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -752,27 +752,30 @@
         <body>
           <![CDATA[
             if (this._scrollingView) {
               this._scrollingView = null;
               window.removeEventListener("mousemove", this, true);
               window.removeEventListener("mousedown", this, true);
               window.removeEventListener("mouseup", this, true);
               window.removeEventListener("contextmenu", this, true);
+              window.removeEventListener("keydown", this, true);
+              window.removeEventListener("keypress", this, true);
+              window.removeEventListener("keyup", this, true);
               clearInterval(this._autoScrollTimer);
             }
          ]]>
        </body>
      </method>
 
       <method name="_createAutoScrollPopup">
         <body>
           <![CDATA[
             const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-            var popup = document.createElementNS(XUL_NS, "popup");
+            var popup = document.createElementNS(XUL_NS, "panel");
             popup.className = "autoscroller";
             return popup;
           ]]>
         </body>
       </method>
      
       <method name="startScroll">
         <parameter name="event"/>
@@ -823,16 +826,19 @@
             this._startY = event.screenY;
             this._screenX = event.screenX;
             this._screenY = event.screenY;
 
             window.addEventListener("mousemove", this, true);
             window.addEventListener("mousedown", this, true);
             window.addEventListener("mouseup", this, true);
             window.addEventListener("contextmenu", this, true);
+            window.addEventListener("keydown", this, true);
+            window.addEventListener("keypress", this, true);
+            window.addEventListener("keyup", this, true);
 
             this._scrollErrorX = 0;
             this._scrollErrorY = 0;
 
             this._autoScrollTimer = setInterval(function(self) { self.autoScrollLoop(); },
                                                 20, this);
          ]]>
        </body>
@@ -946,16 +952,32 @@
                 this._ignoreMouseEvents = false;
                 break;
               }
               case "popuphidden": {
                 this._autoScrollPopup.removeEventListener("popuphidden", this, true);
                 this.stopScroll();
                 break;
               }
+              case "keypress": {
+                if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
+                  // the escape key will be processed by
+                  // nsXULPopupManager::KeyPress and the panel will be closed.
+                  // So, nothing to do here.
+                  break;
+                }
+                // don't break here. we need to eat keypress events.
+              }
+              case "keydown":
+              case "keyup": {
+                // All keyevents should be eaten here during autoscrolling.
+                aEvent.stopPropagation();
+                aEvent.preventDefault();
+                break;
+              }
             }
           }
         ]]>
         </body>
       </method>
 
       <method name="swapDocShells">
         <parameter name="aOtherBrowser"/>