Bug 625151 Reset accesskey state at blur and alt keydown r=enn
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 14 Feb 2012 09:56:03 +0900
changeset 89656 eec3c6a558650dc6071a2c5f69474a8c229c45b5
parent 89655 ca39e09c5a3ff0805bb47c3d91ed53035c549487
child 89657 845f215b717aed8ffc431e03aff6c45911223c51
push id783
push userlsblakk@mozilla.com
push dateTue, 24 Apr 2012 17:33:42 +0000
treeherdermozilla-beta@11faed19f136 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersenn
bugs625151
milestone13.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 625151 Reset accesskey state at blur and alt keydown r=enn
layout/xul/base/src/nsMenuBarListener.cpp
toolkit/content/tests/widgets/window_menubar.xul
--- a/layout/xul/base/src/nsMenuBarListener.cpp
+++ b/layout/xul/base/src/nsMenuBarListener.cpp
@@ -339,46 +339,61 @@ nsMenuBarListener::KeyDown(nsIDOMEvent* 
     return NS_OK;
 
   if (mAccessKey && mAccessKeyFocuses)
   {
     nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
     PRUint32 theChar;
     keyEvent->GetKeyCode(&theChar);
 
-    if (!mAccessKeyDownCanceled && theChar == (PRUint32)mAccessKey &&
-        (GetModifiers(keyEvent) & ~mAccessKeyMask) == 0) {
-      // No other modifiers can be down.
-      // Especially CTRL.  CTRL+ALT == AltGR, and
-      // we'll fuck up on non-US enhanced 102-key
-      // keyboards if we don't check this.
+    // No other modifiers can be down.
+    // Especially CTRL.  CTRL+ALT == AltGR, and we'll fuck up on non-US
+    // enhanced 102-key keyboards if we don't check this.
+    bool isAccessKeyDownEvent =
+      ((theChar == (PRUint32)mAccessKey) &&
+       (GetModifiers(keyEvent) & ~mAccessKeyMask) == 0);
+
+    if (!mAccessKeyDown) {
+      // If accesskey isn't being pressed and the key isn't the accesskey,
+      // ignore the event.
+      if (!isAccessKeyDownEvent) {
+        return NS_OK;
+      }
+
+      // Otherwise, accept the accesskey state.
       mAccessKeyDown = true;
+      mAccessKeyDownCanceled = false;
+      return NS_OK;
     }
-    else {
-      // Some key other than the access key just went down,
-      // so we won't activate the menu bar when the access
-      // key is released.
 
-      mAccessKeyDownCanceled = true;
+    // If the pressed accesskey was canceled already, ignore the event.
+    if (mAccessKeyDownCanceled) {
+      return NS_OK;
     }
+
+    // Some key other than the access key just went down,
+    // so we won't activate the menu bar when the access key is released.
+    mAccessKeyDownCanceled = !isAccessKeyDownEvent;
   }
 
   return NS_OK; // means I am NOT consuming event
 }
 
 ////////////////////////////////////////////////////////////////////////
 
 nsresult
 nsMenuBarListener::Blur(nsIDOMEvent* aEvent)
 {
   if (!mMenuBarFrame->IsMenuOpen() && mMenuBarFrame->IsActive()) {
     ToggleMenuActiveState();
-    mAccessKeyDown = false;
-    mAccessKeyDownCanceled = false;
   }
+  // Reset the accesskey state because we cannot receive the keyup event for
+  // the pressing accesskey.
+  mAccessKeyDown = false;
+  mAccessKeyDownCanceled = false;
   return NS_OK; // means I am NOT consuming event
 }
   
 ////////////////////////////////////////////////////////////////////////
 nsresult 
 nsMenuBarListener::MouseDown(nsIDOMEvent* aMouseEvent)
 {
   // NOTE: MouseDown method listens all phases
--- a/toolkit/content/tests/widgets/window_menubar.xul
+++ b/toolkit/content/tests/widgets/window_menubar.xul
@@ -656,16 +656,47 @@ var popupTests = [
   testname: "unset focus the menubar",
   condition: function() { return (navigator.platform.indexOf("Win") == 0) },
   events: function() {
     return [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ];
   },
   test: function() {
     synthesizeKey("VK_ALT", {  });
   }
+},
+
+// bug 625151
+{
+  testname: "Alt key state before deactivating the window shouldn't prevent " +
+            "next Alt key handling",
+  condition: function() { return (navigator.platform.indexOf("Win") == 0) },
+  events: function() {
+    return [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ];
+  },
+  test: function() {
+    synthesizeKey("VK_ALT", { type: "keydown" });
+    synthesizeKey("VK_TAB", { type: "keydown" }); // cancels the Alt key
+    var thisWindow = window;
+    var newWindow =
+      window.open("data:text/html,", "_blank", "width=100,height=100");
+    newWindow.addEventListener("focus", function () {
+      newWindow.removeEventListener("focus", arguments.callee, false);
+      thisWindow.addEventListener("focus", function () {
+        thisWindow.removeEventListener("focus", arguments.callee, false);
+        setTimeout(function () {
+          synthesizeKey("VK_ALT", { }, thisWindow);
+        }, 0);
+      }, false);
+      newWindow.close();
+      thisWindow.focus();
+      // Note that our window dispatches a hacky key event if IMM is installed
+      // on the system during focus change only if Alt key is pressed.
+      synthesizeKey("`", { type: "keypress" }, thisWindow);
+    }, false);
+  }
 }
 
 ];
 
 ]]>
 </script>
 
 </window>