From cdef5df025d6ca9ab33ee508b33b1c224fcde02a Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 14 Feb 2012 09:56:03 +0900 Subject: [PATCH] Bug 625151 Reset accesskey state at blur and alt keydown r=enn --- layout/xul/base/src/nsMenuBarListener.cpp | 45 ++++++++++++------- .../content/tests/widgets/window_menubar.xul | 31 +++++++++++++ 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/layout/xul/base/src/nsMenuBarListener.cpp b/layout/xul/base/src/nsMenuBarListener.cpp index c5d7db0710d6..2216ae8c1e9d 100644 --- a/layout/xul/base/src/nsMenuBarListener.cpp +++ b/layout/xul/base/src/nsMenuBarListener.cpp @@ -344,21 +344,34 @@ nsMenuBarListener::KeyDown(nsIDOMEvent* 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. - mAccessKeyDown = true; - } - 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. + // 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); - mAccessKeyDownCanceled = true; + 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; } + + // 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 @@ -371,9 +384,11 @@ 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 } diff --git a/toolkit/content/tests/widgets/window_menubar.xul b/toolkit/content/tests/widgets/window_menubar.xul index 1a6a8351c2c9..7a455845b5e0 100644 --- a/toolkit/content/tests/widgets/window_menubar.xul +++ b/toolkit/content/tests/widgets/window_menubar.xul @@ -661,6 +661,37 @@ var popupTests = [ 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); + } } ];