Bug 749563 nsMenuBarListener should ignore consumed alt key events in its keydown and keyup event handlers r=enn
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 10 May 2012 08:25:48 +0900
changeset 97711 e52bf88f2f54c8f1791d29ef887a4d32566c876d
parent 97710 e7f7305c93e577d099a79d55efdabf4c6cf644df
child 97712 2cf8b1f792cec4be949c633d1face3a519b158a2
push id1116
push userlsblakk@mozilla.com
push dateMon, 16 Jul 2012 19:38:18 +0000
treeherdermozilla-beta@95f959a8b4dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersenn
bugs749563
milestone15.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 749563 nsMenuBarListener should ignore consumed alt key events in its keydown and keyup event handlers 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
@@ -156,23 +156,26 @@ nsMenuBarListener::KeyUp(nsIDOMEvent* aK
     domNSEvent->GetIsTrusted(&trustedEvent);
   }
 
   if (!trustedEvent)
     return NS_OK;
 
   if (mAccessKey && mAccessKeyFocuses)
   {
+    bool defaultPrevented = false;
+    aKeyEvent->GetDefaultPrevented(&defaultPrevented);
+
     // On a press of the ALT key by itself, we toggle the menu's 
     // active/inactive state.
     // Get the ascii key code.
     PRUint32 theChar;
     keyEvent->GetKeyCode(&theChar);
 
-    if (mAccessKeyDown && !mAccessKeyDownCanceled &&
+    if (!defaultPrevented && mAccessKeyDown && !mAccessKeyDownCanceled &&
         (PRInt32)theChar == mAccessKey)
     {
       // The access key was down and is now up, and no other
       // keys were pressed in between.
       if (!mMenuBarFrame->IsActive()) {
         mMenuBarFrame->SetActiveByKeyboard();
       }
       ToggleMenuActiveState();
@@ -335,16 +338,19 @@ nsMenuBarListener::KeyDown(nsIDOMEvent* 
     domNSEvent->GetIsTrusted(&trustedEvent);
   }
 
   if (!trustedEvent)
     return NS_OK;
 
   if (mAccessKey && mAccessKeyFocuses)
   {
+    bool defaultPrevented = false;
+    aKeyEvent->GetDefaultPrevented(&defaultPrevented);
+
     nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
     PRUint32 theChar;
     keyEvent->GetKeyCode(&theChar);
 
     // 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 =
@@ -355,22 +361,24 @@ nsMenuBarListener::KeyDown(nsIDOMEvent* 
       // 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;
+      // If default is prevented already, cancel the access key down.
+      mAccessKeyDownCanceled = defaultPrevented;
       return NS_OK;
     }
 
-    // If the pressed accesskey was canceled already, ignore the event.
-    if (mAccessKeyDownCanceled) {
+    // If the pressed accesskey was canceled already or the event was
+    // consumed already, ignore the event.
+    if (mAccessKeyDownCanceled || defaultPrevented) {
       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;
   }
 
--- a/toolkit/content/tests/widgets/window_menubar.xul
+++ b/toolkit/content/tests/widgets/window_menubar.xul
@@ -289,16 +289,50 @@ var popupTests = [
   events: [ "popuphiding viewpopup", "popuphidden viewpopup",
             "DOMMenuItemInactive toolbar", "DOMMenuInactive viewpopup",
             "DOMMenuBarInactive menubar",
             "DOMMenuItemInactive viewmenu" ],
   test: function() { synthesizeKey("VK_ESCAPE", { }); },
   result: function(testname) { checkClosed("viewmenu", testname); },
 },
 {
+  // on Windows, pressing Alt should highlight the first menu but not open it,
+  // but it should be ignored if the alt keydown event is consumed.
+  testname: "alt shouldn't activate menubar if keydown event is consumed",
+  condition: function() { return (navigator.platform.indexOf("Win") == 0) },
+  test: function() {
+    document.addEventListener("keydown", function (aEvent) {
+      document.removeEventListener("keydown", arguments.callee, true);
+      aEvent.preventDefault();
+    }, true);
+    synthesizeKey("VK_ALT", { });
+  },
+  result: function(testname) {
+    ok(!document.getElementById("filemenu").openedWithKey, testname);
+    checkClosed("filemenu", testname);
+  },
+},
+{
+  // on Windows, pressing Alt should highlight the first menu but not open it,
+  // but it should be ignored if the alt keyup event is consumed.
+  testname: "alt shouldn't activate menubar if keyup event is consumed",
+  condition: function() { return (navigator.platform.indexOf("Win") == 0) },
+  test: function() {
+    document.addEventListener("keyup", function (aEvent) {
+      document.removeEventListener("keyup", arguments.callee, true);
+      aEvent.preventDefault();
+    }, true);
+    synthesizeKey("VK_ALT", { });
+  },
+  result: function(testname) {
+    ok(!document.getElementById("filemenu").openedWithKey, testname);
+    checkClosed("filemenu", testname);
+  },
+},
+{
   // on Windows, pressing Alt should highlight the first menu but not open it
   testname: "alt to activate menubar",
   condition: function() { return (navigator.platform.indexOf("Win") == 0) },
   events: [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ],
   test: function() { synthesizeKey("VK_ALT", { }); },
   result: function(testname) {
     is(document.getElementById("filemenu").openedWithKey, true, testname + " openedWithKey");
     checkClosed("filemenu", testname);