diff --git a/layout/xul/base/src/nsMenuBarListener.cpp b/layout/xul/base/src/nsMenuBarListener.cpp index f1004bca2e6c..f356ad585bf5 100644 --- a/layout/xul/base/src/nsMenuBarListener.cpp +++ b/layout/xul/base/src/nsMenuBarListener.cpp @@ -61,8 +61,11 @@ NS_IMPL_QUERY_INTERFACE3(nsMenuBarListener, nsIDOMKeyListener, nsIDOMFocusListen //////////////////////////////////////////////////////////////////////// +nsMenuBarListener::mAccessKey = -1; +nsMenuBarListener::mAccessKeyFocuses = PR_FALSE; + nsMenuBarListener::nsMenuBarListener(nsMenuBarFrame* aMenuBar) - :mAccessKeyDown(PR_FALSE), mAccessKeyFocuses(PR_FALSE), mAccessKey(-1) + :mAccessKeyDown(PR_FALSE) { NS_INIT_REFCNT(); mMenuBarFrame = aMenuBar; @@ -73,6 +76,16 @@ nsMenuBarListener::~nsMenuBarListener() { } +NS_IMETHODIMP +nsMenuBarListener::GetMenuAccessKey(PRInt32* aAccessKey) +{ + if (!aAccessKey) + return NS_ERROR_INVALID_POINTER; + InitAccessKey(); + *aAccessKey = mAccessKey; + return NS_OK; +} + void nsMenuBarListener::InitAccessKey() { if (mAccessKey >= 0) diff --git a/layout/xul/base/src/nsMenuBarListener.h b/layout/xul/base/src/nsMenuBarListener.h index 4e3dfbf9094e..c4a51cba5c82 100644 --- a/layout/xul/base/src/nsMenuBarListener.h +++ b/layout/xul/base/src/nsMenuBarListener.h @@ -60,16 +60,18 @@ public: virtual nsresult MouseDblClick(nsIDOMEvent* aMouseEvent); virtual nsresult MouseOver(nsIDOMEvent* aMouseEvent); virtual nsresult MouseOut(nsIDOMEvent* aMouseEvent); + + static nsresult GetMenuAccessKey(PRInt32* aAccessKey); NS_DECL_ISUPPORTS protected: - void InitAccessKey(); + static void InitAccessKey(); nsMenuBarFrame* mMenuBarFrame; // The menu bar object. PRBool mAccessKeyDown; // Whether or not the ALT key is currently down. - PRBool mAccessKeyFocuses; // Does the access key by itself focus the menubar? - PRInt32 mAccessKey; // See nsIDOMKeyEvent.h for sample values + static PRBool mAccessKeyFocuses; // Does the access key by itself focus the menubar? + static PRInt32 mAccessKey; // See nsIDOMKeyEvent.h for sample values }; diff --git a/layout/xul/base/src/nsMenuListener.cpp b/layout/xul/base/src/nsMenuListener.cpp index 972714807688..50fbc93dc5a7 100644 --- a/layout/xul/base/src/nsMenuListener.cpp +++ b/layout/xul/base/src/nsMenuListener.cpp @@ -84,30 +84,58 @@ nsMenuListener::KeyUp(nsIDOMEvent* aKeyEvent) nsresult nsMenuListener::KeyDown(nsIDOMEvent* aKeyEvent) { -#if !defined(XP_UNIX) || defined(NTO) - // See if the ALT key goes down by itself. - // If so, then close up the menu completely. - nsCOMPtr keyEvent = do_QueryInterface(aKeyEvent); - PRUint32 theChar; - keyEvent->GetKeyCode(&theChar); - PRBool alt; - keyEvent->GetAltKey(&alt); - if (theChar == NS_VK_ALT && alt) { - // 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. - PRBool ctrl,shift,meta; - keyEvent->GetCtrlKey(&ctrl); - keyEvent->GetShiftKey(&shift); - keyEvent->GetMetaKey(&meta); - if (!(ctrl || shift || meta)) { - // The ALT key just went down by itself. This means kill - // the menu. - mMenuParent->DismissChain(); + PRInt32 menuAccessKey = -1; + nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); + if (menuAccessKey) { + PRUint32 theChar; + nsCOMPtr keyEvent = do_QueryInterface(aKeyEvent); + keyEvent->GetKeyCode(&theChar); + + PRBool access = PR_FALSE; + PRBool accessKeyDown = PR_FALSE; + switch (menuAccessKey) + { + case nsIDOMKeyEvent::DOM_VK_CONTROL: + keyEvent->GetCtrlKey(&access); + break; + case nsIDOMKeyEvent::DOM_VK_ALT: + keyEvent->GetAltKey(&access); + break; + case nsIDOMKeyEvent::DOM_VK_META: + keyEvent->GetMetaKey(&access); + break; + default: + access = 0; } + if (theChar == nsIDOMKeyEvent::DOM_VK_TAB && accessKeyDown) { + accessKeyDown = PR_FALSE; + } + + if (theChar == (PRUint32)menuAccessKey || access) { + // 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. + PRBool ctrl = PR_FALSE; + if (menuAccessKey != nsIDOMKeyEvent::DOM_VK_CONTROL) + keyEvent->GetCtrlKey(&ctrl); + PRBool alt=PR_FALSE; + if (menuAccessKey != nsIDOMKeyEvent::DOM_VK_ALT) + keyEvent->GetAltKey(&alt); + PRBool shift=PR_FALSE; + if (menuAccessKey != nsIDOMKeyEvent::DOM_VK_SHIFT) + keyEvent->GetShiftKey(&shift); + PRBool meta=PR_FALSE; + if (menuAccessKey != nsIDOMKeyEvent::DOM_VK_META) + keyEvent->GetMetaKey(&meta); + if (!(ctrl || alt || shift || meta)) { + // The access key just went down by itself. Track this. + accessKeyDown = PR_TRUE; + } + } + if (accessKeyDown) + mMenuParent->DismissChain(); } -#endif aKeyEvent->PreventBubble(); aKeyEvent->PreventCapture(); @@ -144,15 +172,17 @@ nsMenuListener::KeyPress(nsIDOMEvent* aKeyEvent) // Open one level. mMenuParent->Enter(); } -#if !defined(XP_UNIX) || defined(NTO) else { - // Do shortcut navigation. - // A letter was pressed. We want to see if a shortcut gets matched. If - // so, we'll know the menu got activated. - keyEvent->GetCharCode(&theChar); - mMenuParent->ShortcutNavigation(theChar, handled); + PRInt32 menuAccessKey = -1; + nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); + if (menuAccessKey) { + // Do shortcut navigation. + // A letter was pressed. We want to see if a shortcut gets matched. If + // so, we'll know the menu got activated. + keyEvent->GetCharCode(&theChar); + mMenuParent->ShortcutNavigation(theChar, handled); + } } -#endif aKeyEvent->PreventBubble(); aKeyEvent->PreventCapture(); diff --git a/layout/xul/base/src/nsTextBoxFrame.cpp b/layout/xul/base/src/nsTextBoxFrame.cpp index 3fad72b8336c..deea8a541254 100644 --- a/layout/xul/base/src/nsTextBoxFrame.cpp +++ b/layout/xul/base/src/nsTextBoxFrame.cpp @@ -39,6 +39,7 @@ #include "nsIContent.h" #include "nsINameSpaceManager.h" #include "nsBoxLayoutState.h" +#include "nsMenuBarListener.h" #define ELIPSIS "..." @@ -134,32 +135,35 @@ nsTextBoxFrame::Init(nsIPresContext* aPresContext, // the following block is to append the accesskey to to mTitle if there is an accesskey // but the mTitle doesn't have the character - // XXX Should this code first check to see if there's a menuAccessKey? - nsAutoString accesskey; - mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, - accesskey); - if (!accesskey.IsEmpty()) { - if (!mAccessKeyInfo) - mAccessKeyInfo = new nsAccessKeyInfo(); + PRInt32 menuAccessKey; + nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); + if (menuAccessKey) { + nsAutoString accesskey; + mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, + accesskey); + if (!accesskey.IsEmpty()) { + if (!mAccessKeyInfo) + mAccessKeyInfo = new nsAccessKeyInfo(); - mAccessKeyInfo->mAccesskeyIndex = -1; - mAccessKeyInfo->mAccesskeyIndex = mTitle.Find(accesskey, PR_TRUE); + mAccessKeyInfo->mAccesskeyIndex = -1; + mAccessKeyInfo->mAccesskeyIndex = mTitle.Find(accesskey, PR_TRUE); if (mAccessKeyInfo->mAccesskeyIndex == -1) { - nsAutoString tmpstring; tmpstring.AssignWithConversion("("); - accesskey.ToUpperCase(); - tmpstring += accesskey; - tmpstring.AppendWithConversion(")"); - PRUint32 offset = mTitle.RFind("..."); - if ( offset != kNotFound) - mTitle.Insert(tmpstring,offset); - else - mTitle += tmpstring; + nsAutoString tmpstring; tmpstring.AssignWithConversion("("); + accesskey.ToUpperCase(); + tmpstring += accesskey; + tmpstring.AppendWithConversion(")"); + PRUint32 offset = mTitle.RFind("..."); + if ( offset != (PRUint32)kNotFound) + mTitle.Insert(tmpstring,offset); + else + mTitle += tmpstring; } - } else { - if (mAccessKeyInfo) { - delete mAccessKeyInfo; - mAccessKeyInfo = nsnull; + } else { + if (mAccessKeyInfo) { + delete mAccessKeyInfo; + mAccessKeyInfo = nsnull; + } } } @@ -535,7 +539,9 @@ nsTextBoxFrame::CalculateTitleForWidth(nsIPresContext* aPresContext, nsIRenderin void nsTextBoxFrame::UpdateAccessUnderline() { -#ifndef XP_UNIX + PRInt32 menuAccessKey = -1; + nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); + if (menuAccessKey) { nsAutoString accesskey; mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, accesskey); @@ -552,7 +558,7 @@ nsTextBoxFrame::UpdateAccessUnderline() mAccessKeyInfo->mAccesskeyIndex = -1; mAccessKeyInfo->mAccesskeyIndex = mCroppedTitle.Find(accesskey, PR_TRUE); -#endif + } } diff --git a/layout/xul/base/src/nsTitledButtonFrame.cpp b/layout/xul/base/src/nsTitledButtonFrame.cpp index 77007de172f0..89a47319c66e 100644 --- a/layout/xul/base/src/nsTitledButtonFrame.cpp +++ b/layout/xul/base/src/nsTitledButtonFrame.cpp @@ -73,6 +73,7 @@ #include "nsIStyleSet.h" #include "nsIStyleContext.h" #include "nsBoxLayoutState.h" +#include "nsMenuBarListener.h" #include "nsFormControlHelper.h" @@ -303,27 +304,31 @@ nsTitledButtonFrame::Init(nsIPresContext* aPresContext, PRBool a,b,c; UpdateAttributes(aPresContext, nsnull, a, b, c /* all */); + PRInt32 menuAccessKey = -1; + nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); + if (menuAccessKey) { + // the following block is to append the accesskey to to mTitle if there is an accesskey // but the mTitle doesn't have the character - // XXX Should this code first check to see if there's a menuAccessKey? - mAccesskeyIndex = -1; - nsAutoString accesskey; - mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, - accesskey); - if (!accesskey.IsEmpty()) { + mAccesskeyIndex = -1; + nsAutoString accesskey; + mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, + accesskey); + if (!accesskey.IsEmpty()) { mAccesskeyIndex = mTitle.Find(accesskey, PR_TRUE); if (mAccesskeyIndex == -1) { - nsString tmpstring; tmpstring.AssignWithConversion("("); - accesskey.ToUpperCase(); - tmpstring += accesskey; - tmpstring.AppendWithConversion(")"); - PRUint32 offset = mTitle.RFind("..."); - if ( offset != kNotFound) - mTitle.Insert(tmpstring,offset); - else - mTitle += tmpstring; + nsString tmpstring; tmpstring.AssignWithConversion("("); + accesskey.ToUpperCase(); + tmpstring += accesskey; + tmpstring.AppendWithConversion(")"); + PRUint32 offset = mTitle.RFind("..."); + if ( offset != (PRUint32)kNotFound) + mTitle.Insert(tmpstring,offset); + else + mTitle += tmpstring; } + } } return rv; @@ -819,8 +824,9 @@ nsTitledButtonFrame::CalculateTitleForWidth(nsIPresContext* aPresContext, nsIRen void nsTitledButtonFrame::UpdateAccessUnderline() { - mAccesskeyIndex = -1; -#ifndef XP_UNIX + PRInt32 menuAccessKey = -1; + nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); + if (menuAccessKey) { nsAutoString accesskey; mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, accesskey); @@ -829,7 +835,7 @@ nsTitledButtonFrame::UpdateAccessUnderline() mAccesskeyIndex = mCroppedTitle.Find(accesskey, PR_TRUE); mNeedsAccessUpdate = PR_TRUE; -#endif + } } NS_IMETHODIMP