diff --git a/content/xbl/src/nsXBLEventHandler.cpp b/content/xbl/src/nsXBLEventHandler.cpp index ca2af0ebb3f7..6db39a2fd2b7 100644 --- a/content/xbl/src/nsXBLEventHandler.cpp +++ b/content/xbl/src/nsXBLEventHandler.cpp @@ -45,6 +45,10 @@ #include "nsIDOMEventReceiver.h" #include "nsXBLBinding.h" #include "nsIPrivateDOMEvent.h" +#include "nsIPref.h" +#include "nsIServiceManager.h" + +static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); PRUint32 nsXBLEventHandler::gRefCnt = 0; nsIAtom* nsXBLEventHandler::kKeyCodeAtom = nsnull; @@ -71,6 +75,7 @@ nsXBLEventHandler::nsXBLEventHandler(nsIContent* aBoundElement, nsIContent* aHan mEventName.Assign(aEventName); mNextHandler = nsnull; gRefCnt++; + mAccessKey = -1; if (gRefCnt == 1) { kKeyCodeAtom = NS_NewAtom("keycode"); kKeyAtom = NS_NewAtom("key"); @@ -371,7 +376,38 @@ nsresult nsXBLEventHandler::Destroy(nsIDOMEvent* aEvent) return NS_OK; } -/////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// Get the menu access key from prefs. +// XXX Eventually pick up using CSS3 key-equivalent property or somesuch +void +nsXBLEventHandler::InitAccessKey() +{ + if (mAccessKey >= 0) + return; + + // Compiled-in defaults, in case we can't get the pref -- + // mac doesn't have menu shortcuts, other platforms use alt. +#ifndef XP_MAC + mAccessKey = nsIDOMKeyEvent::DOM_VK_ALT; +#else + mAccessKey = 0; +#endif + + // Get the menu access key value from prefs, overriding the default: + nsresult rv; + NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv); + if (NS_SUCCEEDED(rv) && prefs) + { + rv = prefs->GetIntPref("ui.key.menuAccessKey", &mAccessKey); + } +#ifdef DEBUG_akkana + if (NS_FAILED(rv)) + { + NS_ASSERTION(PR_FALSE,"XBLEventHandler couldn't get menu access key from prefs!\n"); + } +#endif +} + PRBool nsXBLEventHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent) @@ -409,31 +445,31 @@ nsXBLEventHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent) // Now check modifier keys nsAutoString modifier; - PRBool isModifierPresent; mHandlerElement->GetAttribute(kNameSpaceID_None, kPrimaryAtom, modifier); - if (modifier == trueString) { - // The XUL key must be set. Hard code for now. - // XXX Eventually pick up using CSS3 key-equivalent property or somesuch -#ifdef XP_MAC - aKeyEvent->GetMetaKey(&isModifierPresent); -#elif XP_UNIX - aKeyEvent->GetAltKey(&isModifierPresent); -#else - aKeyEvent->GetCtrlKey(&isModifierPresent); -#endif + // Get the xulkey. + InitAccessKey(); + PRBool isModifierPresent = PR_FALSE; + switch (mAccessKey) + { + case nsIDOMKeyEvent::DOM_VK_META: + aKeyEvent->GetMetaKey(&isModifierPresent); + break; + + case nsIDOMKeyEvent::DOM_VK_ALT: + aKeyEvent->GetAltKey(&isModifierPresent); + break; + + case nsIDOMKeyEvent::DOM_VK_CONTROL: + default: + aKeyEvent->GetCtrlKey(&isModifierPresent); + } + + if (modifier == trueString) { if (!isModifierPresent) return PR_FALSE; } else if (modifier == falseString) { -#ifdef XP_MAC - aKeyEvent->GetMetaKey(&isModifierPresent); -#elif XP_UNIX - aKeyEvent->GetAltKey(&isModifierPresent); -#else - aKeyEvent->GetCtrlKey(&isModifierPresent); -#endif - if (isModifierPresent) return PR_FALSE; } @@ -505,31 +541,30 @@ nsXBLEventHandler::MouseEventMatched(nsIDOMMouseEvent* aMouseEvent) // XXX Check for button and modifier keys. // Now check modifier keys nsAutoString modifier; - PRBool isModifierPresent; mHandlerElement->GetAttribute(kNameSpaceID_None, kPrimaryAtom, modifier); - if (modifier == trueString) { - // The XUL key must be set. Hard code for now. - // XXX Eventually pick up using CSS3 key-equivalent property or somesuch -#ifdef XP_MAC - aMouseEvent->GetMetaKey(&isModifierPresent); -#elif XP_UNIX - aMouseEvent->GetAltKey(&isModifierPresent); -#else - aMouseEvent->GetCtrlKey(&isModifierPresent); -#endif + // Get the xulkey + InitAccessKey(); + PRBool isModifierPresent = PR_FALSE; + switch (mAccessKey) + { + case nsIDOMKeyEvent::DOM_VK_META: + aMouseEvent->GetMetaKey(&isModifierPresent); + break; + + case nsIDOMKeyEvent::DOM_VK_ALT: + aMouseEvent->GetAltKey(&isModifierPresent); + break; + + case nsIDOMKeyEvent::DOM_VK_CONTROL: + default: + aMouseEvent->GetCtrlKey(&isModifierPresent); + } + if (modifier == trueString) { if (!isModifierPresent) return PR_FALSE; } else if (modifier == falseString) { -#ifdef XP_MAC - aMouseEvent->GetMetaKey(&isModifierPresent); -#elif XP_UNIX - aMouseEvent->GetAltKey(&isModifierPresent); -#else - aMouseEvent->GetCtrlKey(&isModifierPresent); -#endif - if (isModifierPresent) return PR_FALSE; } diff --git a/content/xbl/src/nsXBLEventHandler.h b/content/xbl/src/nsXBLEventHandler.h index 13537f4bf0c0..ec76aa87c47d 100644 --- a/content/xbl/src/nsXBLEventHandler.h +++ b/content/xbl/src/nsXBLEventHandler.h @@ -130,6 +130,9 @@ protected: nsIContent* mHandlerElement; nsAutoString mEventName; + void InitAccessKey(); + PRInt32 mAccessKey; // the default access key or "xulkey" + nsXBLEventHandler* mNextHandler; // Handlers are chained for easy unloading later. }; diff --git a/dom/public/coreEvents/nsIDOMKeyEvent.h b/dom/public/coreEvents/nsIDOMKeyEvent.h index d282623f2015..25b9aa00056f 100644 --- a/dom/public/coreEvents/nsIDOMKeyEvent.h +++ b/dom/public/coreEvents/nsIDOMKeyEvent.h @@ -150,7 +150,8 @@ public: DOM_VK_OPEN_BRACKET = 219, DOM_VK_BACK_SLASH = 220, DOM_VK_CLOSE_BRACKET = 221, - DOM_VK_QUOTE = 222 + DOM_VK_QUOTE = 222, + DOM_VK_META = 224 }; NS_IMETHOD GetCharCode(PRUint32* aCharCode)=0; diff --git a/dom/public/idl/events/MouseKeyEvent.idl b/dom/public/idl/events/MouseKeyEvent.idl index 1fcd7c231ec5..931e0d2b0080 100644 --- a/dom/public/idl/events/MouseKeyEvent.idl +++ b/dom/public/idl/events/MouseKeyEvent.idl @@ -123,6 +123,8 @@ const unsigned long DOM_VK_CLOSE_BRACKET = 0xDD; const unsigned long DOM_VK_QUOTE = 0xDE; + const unsigned long DOM_VK_META = 0xE0; + readonly attribute unsigned long charCode; readonly attribute unsigned long keyCode; diff --git a/layout/xbl/src/nsXBLEventHandler.cpp b/layout/xbl/src/nsXBLEventHandler.cpp index ca2af0ebb3f7..6db39a2fd2b7 100644 --- a/layout/xbl/src/nsXBLEventHandler.cpp +++ b/layout/xbl/src/nsXBLEventHandler.cpp @@ -45,6 +45,10 @@ #include "nsIDOMEventReceiver.h" #include "nsXBLBinding.h" #include "nsIPrivateDOMEvent.h" +#include "nsIPref.h" +#include "nsIServiceManager.h" + +static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); PRUint32 nsXBLEventHandler::gRefCnt = 0; nsIAtom* nsXBLEventHandler::kKeyCodeAtom = nsnull; @@ -71,6 +75,7 @@ nsXBLEventHandler::nsXBLEventHandler(nsIContent* aBoundElement, nsIContent* aHan mEventName.Assign(aEventName); mNextHandler = nsnull; gRefCnt++; + mAccessKey = -1; if (gRefCnt == 1) { kKeyCodeAtom = NS_NewAtom("keycode"); kKeyAtom = NS_NewAtom("key"); @@ -371,7 +376,38 @@ nsresult nsXBLEventHandler::Destroy(nsIDOMEvent* aEvent) return NS_OK; } -/////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// Get the menu access key from prefs. +// XXX Eventually pick up using CSS3 key-equivalent property or somesuch +void +nsXBLEventHandler::InitAccessKey() +{ + if (mAccessKey >= 0) + return; + + // Compiled-in defaults, in case we can't get the pref -- + // mac doesn't have menu shortcuts, other platforms use alt. +#ifndef XP_MAC + mAccessKey = nsIDOMKeyEvent::DOM_VK_ALT; +#else + mAccessKey = 0; +#endif + + // Get the menu access key value from prefs, overriding the default: + nsresult rv; + NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv); + if (NS_SUCCEEDED(rv) && prefs) + { + rv = prefs->GetIntPref("ui.key.menuAccessKey", &mAccessKey); + } +#ifdef DEBUG_akkana + if (NS_FAILED(rv)) + { + NS_ASSERTION(PR_FALSE,"XBLEventHandler couldn't get menu access key from prefs!\n"); + } +#endif +} + PRBool nsXBLEventHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent) @@ -409,31 +445,31 @@ nsXBLEventHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent) // Now check modifier keys nsAutoString modifier; - PRBool isModifierPresent; mHandlerElement->GetAttribute(kNameSpaceID_None, kPrimaryAtom, modifier); - if (modifier == trueString) { - // The XUL key must be set. Hard code for now. - // XXX Eventually pick up using CSS3 key-equivalent property or somesuch -#ifdef XP_MAC - aKeyEvent->GetMetaKey(&isModifierPresent); -#elif XP_UNIX - aKeyEvent->GetAltKey(&isModifierPresent); -#else - aKeyEvent->GetCtrlKey(&isModifierPresent); -#endif + // Get the xulkey. + InitAccessKey(); + PRBool isModifierPresent = PR_FALSE; + switch (mAccessKey) + { + case nsIDOMKeyEvent::DOM_VK_META: + aKeyEvent->GetMetaKey(&isModifierPresent); + break; + + case nsIDOMKeyEvent::DOM_VK_ALT: + aKeyEvent->GetAltKey(&isModifierPresent); + break; + + case nsIDOMKeyEvent::DOM_VK_CONTROL: + default: + aKeyEvent->GetCtrlKey(&isModifierPresent); + } + + if (modifier == trueString) { if (!isModifierPresent) return PR_FALSE; } else if (modifier == falseString) { -#ifdef XP_MAC - aKeyEvent->GetMetaKey(&isModifierPresent); -#elif XP_UNIX - aKeyEvent->GetAltKey(&isModifierPresent); -#else - aKeyEvent->GetCtrlKey(&isModifierPresent); -#endif - if (isModifierPresent) return PR_FALSE; } @@ -505,31 +541,30 @@ nsXBLEventHandler::MouseEventMatched(nsIDOMMouseEvent* aMouseEvent) // XXX Check for button and modifier keys. // Now check modifier keys nsAutoString modifier; - PRBool isModifierPresent; mHandlerElement->GetAttribute(kNameSpaceID_None, kPrimaryAtom, modifier); - if (modifier == trueString) { - // The XUL key must be set. Hard code for now. - // XXX Eventually pick up using CSS3 key-equivalent property or somesuch -#ifdef XP_MAC - aMouseEvent->GetMetaKey(&isModifierPresent); -#elif XP_UNIX - aMouseEvent->GetAltKey(&isModifierPresent); -#else - aMouseEvent->GetCtrlKey(&isModifierPresent); -#endif + // Get the xulkey + InitAccessKey(); + PRBool isModifierPresent = PR_FALSE; + switch (mAccessKey) + { + case nsIDOMKeyEvent::DOM_VK_META: + aMouseEvent->GetMetaKey(&isModifierPresent); + break; + + case nsIDOMKeyEvent::DOM_VK_ALT: + aMouseEvent->GetAltKey(&isModifierPresent); + break; + + case nsIDOMKeyEvent::DOM_VK_CONTROL: + default: + aMouseEvent->GetCtrlKey(&isModifierPresent); + } + if (modifier == trueString) { if (!isModifierPresent) return PR_FALSE; } else if (modifier == falseString) { -#ifdef XP_MAC - aMouseEvent->GetMetaKey(&isModifierPresent); -#elif XP_UNIX - aMouseEvent->GetAltKey(&isModifierPresent); -#else - aMouseEvent->GetCtrlKey(&isModifierPresent); -#endif - if (isModifierPresent) return PR_FALSE; } diff --git a/layout/xbl/src/nsXBLEventHandler.h b/layout/xbl/src/nsXBLEventHandler.h index 13537f4bf0c0..ec76aa87c47d 100644 --- a/layout/xbl/src/nsXBLEventHandler.h +++ b/layout/xbl/src/nsXBLEventHandler.h @@ -130,6 +130,9 @@ protected: nsIContent* mHandlerElement; nsAutoString mEventName; + void InitAccessKey(); + PRInt32 mAccessKey; // the default access key or "xulkey" + nsXBLEventHandler* mNextHandler; // Handlers are chained for easy unloading later. }; diff --git a/layout/xul/base/src/nsMenuBarListener.cpp b/layout/xul/base/src/nsMenuBarListener.cpp index 2bb2e26a0f63..91adf9e6fa1b 100644 --- a/layout/xul/base/src/nsMenuBarListener.cpp +++ b/layout/xul/base/src/nsMenuBarListener.cpp @@ -46,6 +46,10 @@ #include "nsIView.h" #include "nsISupportsArray.h" +#include "nsIPref.h" + +static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); + /* * nsMenuBarListener implementation */ @@ -58,7 +62,7 @@ NS_IMPL_QUERY_INTERFACE3(nsMenuBarListener, nsIDOMKeyListener, nsIDOMFocusListen //////////////////////////////////////////////////////////////////////// nsMenuBarListener::nsMenuBarListener(nsMenuBarFrame* aMenuBar) -:mAltKeyDown(PR_FALSE) + :mAccessKeyDown(PR_FALSE), mAccessKey(-1) { NS_INIT_REFCNT(); mMenuBarFrame = aMenuBar; @@ -69,34 +73,64 @@ nsMenuBarListener::~nsMenuBarListener() { } +void nsMenuBarListener::InitAccessKey() +{ + if (mAccessKey >= 0) + return; + // Compiled-in defaults, in case we can't get LookAndFeel -- + // mac doesn't have menu shortcuts, other platforms use alt. +#ifndef XP_MAC + mAccessKey = nsIDOMKeyEvent::DOM_VK_ALT; +#else + mAccessKey = 0; +#endif + + // Get the menu access key value from prefs, overriding the default: + nsresult rv; + NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv); + if (NS_SUCCEEDED(rv) && prefs) + { + rv = prefs->GetIntPref("ui.key.menuAccessKey", &mAccessKey); + } +#ifdef DEBUG_akkana + if (NS_FAILED(rv)) + { + NS_ASSERTION(PR_FALSE,"Menubar listener couldn't get accel key from prefs!\n"); + } +#endif +} //////////////////////////////////////////////////////////////////////// nsresult nsMenuBarListener::KeyUp(nsIDOMEvent* aKeyEvent) { - // On a press of the ALT key by itself, we toggle the menu's - // active/inactive state. - // Get the ascii key code. - nsCOMPtr keyEvent = do_QueryInterface(aKeyEvent); - PRUint32 theChar; - keyEvent->GetKeyCode(&theChar); + InitAccessKey(); -#if !defined(XP_UNIX) || defined(NTO) - if (theChar == NS_VK_ALT && mAltKeyDown) { - // The ALT key was down and is now up. - mMenuBarFrame->ToggleMenuActiveState(); + if (mAccessKey) + { + // On a press of the ALT key by itself, we toggle the menu's + // active/inactive state. + // Get the ascii key code. + nsCOMPtr keyEvent = do_QueryInterface(aKeyEvent); + PRUint32 theChar; + keyEvent->GetKeyCode(&theChar); + + if (mAccessKeyDown && (PRInt32)theChar == mAccessKey) + { + // The access key was down and is now up. + mMenuBarFrame->ToggleMenuActiveState(); + } + mAccessKeyDown = PR_FALSE; + + PRBool active = mMenuBarFrame->IsActive(); + if (active) { + aKeyEvent->PreventBubble(); + aKeyEvent->PreventCapture(); + aKeyEvent->PreventDefault(); + return NS_ERROR_BASE; // I am consuming event + } } - mAltKeyDown = PR_FALSE; -#endif - - PRBool active = mMenuBarFrame->IsActive(); - if (active) { - aKeyEvent->PreventBubble(); - aKeyEvent->PreventCapture(); - aKeyEvent->PreventDefault(); - return NS_ERROR_BASE; // I am consuming event - } return NS_OK; // means I am NOT consuming event } @@ -105,36 +139,39 @@ nsMenuBarListener::KeyUp(nsIDOMEvent* aKeyEvent) nsresult nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent) { -#if !defined(XP_UNIX) || defined(NTO) - nsCOMPtr nsUIEvent = do_QueryInterface(aKeyEvent); - PRBool preventDefault; + InitAccessKey(); - nsUIEvent->GetPreventDefault(&preventDefault); - if (!preventDefault) { - nsCOMPtr keyEvent = do_QueryInterface(aKeyEvent); - PRUint32 theChar; - keyEvent->GetKeyCode(&theChar); + if (mAccessKey) + { + nsCOMPtr nsUIEvent = do_QueryInterface(aKeyEvent); + PRBool preventDefault; - if (mAltKeyDown && (theChar != NS_VK_ALT)) { - mAltKeyDown = PR_FALSE; + nsUIEvent->GetPreventDefault(&preventDefault); + if (!preventDefault) { + nsCOMPtr keyEvent = do_QueryInterface(aKeyEvent); + PRUint32 theChar; + keyEvent->GetKeyCode(&theChar); - // 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); + if (mAccessKeyDown && ((PRInt32)theChar != mAccessKey)) { + mAccessKeyDown = PR_FALSE; - PRBool active = PR_FALSE; - mMenuBarFrame->ShortcutNavigation(theChar, active); + // 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); - if (active) { - aKeyEvent->PreventBubble(); - aKeyEvent->PreventCapture(); - aKeyEvent->PreventDefault(); - } - return NS_ERROR_BASE; // I am consuming event - } - } -#endif + PRBool active = PR_FALSE; + mMenuBarFrame->ShortcutNavigation(theChar, active); + + if (active) { + aKeyEvent->PreventBubble(); + aKeyEvent->PreventCapture(); + aKeyEvent->PreventDefault(); + } + return NS_ERROR_BASE; // I am consuming event + } + } + } return NS_OK; } @@ -142,31 +179,56 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent) nsresult nsMenuBarListener::KeyDown(nsIDOMEvent* aKeyEvent) { -#if !defined(XP_UNIX) || defined(NTO) - nsCOMPtr keyEvent = do_QueryInterface(aKeyEvent); - PRUint32 theChar; - keyEvent->GetKeyCode(&theChar); - PRBool alt; - keyEvent->GetAltKey(&alt); - if (theChar == NS_VK_TAB && mAltKeyDown) { - mAltKeyDown = PR_FALSE; - } + InitAccessKey(); - 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. Track this. - mAltKeyDown = PR_TRUE; + if (mAccessKey) + { + nsCOMPtr keyEvent = do_QueryInterface(aKeyEvent); + PRUint32 theChar; + keyEvent->GetKeyCode(&theChar); + + PRBool access; + switch (mAccessKey) + { + 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 && mAccessKeyDown) { + mAccessKeyDown = PR_FALSE; + } + + if (theChar == mAccessKey || 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 (mAccessKey != nsIDOMKeyEvent::DOM_VK_CONTROL) + keyEvent->GetCtrlKey(&ctrl); + PRBool alt=PR_FALSE; + if (mAccessKey != nsIDOMKeyEvent::DOM_VK_ALT) + keyEvent->GetAltKey(&alt); + PRBool shift=PR_FALSE; + if (mAccessKey != nsIDOMKeyEvent::DOM_VK_SHIFT) + keyEvent->GetShiftKey(&shift); + PRBool meta=PR_FALSE; + if (mAccessKey != nsIDOMKeyEvent::DOM_VK_META) + keyEvent->GetMetaKey(&meta); + if (!(ctrl || alt || shift || meta)) { + // The access key just went down by itself. Track this. + mAccessKeyDown = PR_TRUE; + } } } -#endif return NS_OK; // means I am NOT consuming event } @@ -187,7 +249,7 @@ nsMenuBarListener::Blur(nsIDOMEvent* aEvent) mMenuBarFrame->ToggleMenuActiveState(); PRBool handled; mMenuBarFrame->Escape(handled); - mAltKeyDown = PR_FALSE; + mAccessKeyDown = PR_FALSE; } return NS_OK; // means I am NOT consuming event } @@ -200,7 +262,7 @@ nsMenuBarListener::MouseDown(nsIDOMEvent* aMouseEvent) mMenuBarFrame->ToggleMenuActiveState(); PRBool handled; mMenuBarFrame->Escape(handled); - mAltKeyDown = PR_FALSE; + mAccessKeyDown = PR_FALSE; } return NS_OK; // means I am NOT consuming event } diff --git a/layout/xul/base/src/nsMenuBarListener.h b/layout/xul/base/src/nsMenuBarListener.h index dd8f1ad5201f..af80ab051d37 100644 --- a/layout/xul/base/src/nsMenuBarListener.h +++ b/layout/xul/base/src/nsMenuBarListener.h @@ -64,8 +64,11 @@ public: NS_DECL_ISUPPORTS protected: + void InitAccessKey(); + nsMenuBarFrame* mMenuBarFrame; // The menu bar object. - PRBool mAltKeyDown; // Whether or not the ALT key is currently down. + PRBool mAccessKeyDown; // Whether or not the ALT key is currently down. + PRInt32 mAccessKey; // See nsIDOMKeyEvent.h for sample values }; diff --git a/layout/xul/base/src/nsMenuFrame.cpp b/layout/xul/base/src/nsMenuFrame.cpp index ba5d12ebaa10..1e16841f75e8 100644 --- a/layout/xul/base/src/nsMenuFrame.cpp +++ b/layout/xul/base/src/nsMenuFrame.cpp @@ -63,7 +63,9 @@ #include "nsIServiceManager.h" #include "nsIXBLService.h" #include "nsCSSFrameConstructor.h" - +#include "nsIDOMKeyEvent.h" +#include "nsIPref.h" + #define NS_MENU_POPUP_LIST_INDEX 0 static PRInt32 gEatMouseMove = PR_FALSE; @@ -72,7 +74,7 @@ nsMenuDismissalListener* nsMenuFrame::mDismissalListener = nsnull; static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); static NS_DEFINE_IID(kILookAndFeelIID, NS_ILOOKANDFEEL_IID); - +static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); // // NS_NewMenuFrame @@ -135,7 +137,7 @@ nsMenuFrame::nsMenuFrame(nsIPresShell* aShell):nsBoxFrame(aShell), NS_IMETHODIMP nsMenuFrame::SetParent(const nsIFrame* aParent) { - nsresult rv = nsBoxFrame::SetParent(aParent); + nsBoxFrame::SetParent(aParent); nsIFrame* currFrame = (nsIFrame*)aParent; while (!mMenuParent && currFrame) { // Set our menu parent. @@ -1363,61 +1365,79 @@ nsMenuFrame::BuildAcceleratorText(nsString& aAccelString) nsAutoString keyAtom; keyAtom.AssignWithConversion("key"); nsAutoString shiftAtom; shiftAtom.AssignWithConversion("shift"); - nsAutoString altAtom; altAtom.AssignWithConversion("alt"); - nsAutoString commandAtom; commandAtom.AssignWithConversion("command"); + nsAutoString altAtom; altAtom.AssignWithConversion("alt"); + nsAutoString commandAtom; commandAtom.AssignWithConversion("command"); nsAutoString controlAtom; controlAtom.AssignWithConversion("control"); - nsAutoString shiftValue; - nsAutoString altValue; - nsAutoString commandValue; + nsAutoString shiftValue; + nsAutoString altValue; + nsAutoString commandValue; nsAutoString controlValue; - nsAutoString keyChar; keyChar.AssignWithConversion(" "); + nsAutoString keyChar; keyChar.AssignWithConversion(" "); - keyElement->GetAttribute(keyAtom, keyChar); - keyElement->GetAttribute(shiftAtom, shiftValue); - keyElement->GetAttribute(altAtom, altValue); - keyElement->GetAttribute(commandAtom, commandValue); + keyElement->GetAttribute(keyAtom, keyChar); + keyElement->GetAttribute(shiftAtom, shiftValue); + keyElement->GetAttribute(altAtom, altValue); + keyElement->GetAttribute(commandAtom, commandValue); keyElement->GetAttribute(controlAtom, controlValue); - nsAutoString xulkey; - keyElement->GetAttribute(NS_ConvertASCIItoUCS2("xulkey"), xulkey); - if (xulkey.EqualsWithConversion("true")) { - // Set the default for the xul key modifier -#ifdef XP_MAC - commandValue.AssignWithConversion("true"); -#elif defined(XP_PC) || defined(NTO) - controlValue.AssignWithConversion("true"); -#else - altValue.AssignWithConversion("true"); -#endif - } - + PRInt32 accelKey = 0; + PRBool prependPlus = PR_FALSE; - if(!commandValue.IsEmpty() && !commandValue.EqualsWithConversion("false")) { - prependPlus = PR_TRUE; - aAccelString.AppendWithConversion("Ctrl"); // Hmmm. Kinda defeats the point of having an abstraction. + nsAutoString xulkey; + keyElement->GetAttribute(NS_ConvertASCIItoUCS2("xulkey"), xulkey); + if (xulkey.EqualsWithConversion("true")) + { + // Compiled-in defaults, in case we can't get LookAndFeel -- + // command for mac, control for all other platforms. +#ifdef XP_MAC + accelKey = nsIDOMKeyEvent::DOM_VK_META; +#else + accelKey = nsIDOMKeyEvent::DOM_VK_CONTROL; +#endif + + // Get the accelerator key value from prefs, overriding the default: + nsresult rv; + NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv); + if (NS_SUCCEEDED(rv) && prefs) + { + rv = prefs->GetIntPref("ui.key.acceleratorKey", &accelKey); + } +#ifdef DEBUG_akkana + else + { + NS_ASSERTION(PR_FALSE,"Menu couldn't get accel key from prefs!\n"); + } +#endif + + switch (accelKey) + { + case nsIDOMKeyEvent::DOM_VK_META: + prependPlus = PR_TRUE; + aAccelString.AppendWithConversion("Ctrl"); // Hmmm. Kinda defeats the point of having an abstraction. + break; + + case nsIDOMKeyEvent::DOM_VK_ALT: + prependPlus = PR_TRUE; + aAccelString.AppendWithConversion("Alt"); + break; + + case nsIDOMKeyEvent::DOM_VK_CONTROL: + default: + prependPlus = PR_TRUE; + aAccelString.AppendWithConversion("Ctrl"); + break; + } } - if(!controlValue.IsEmpty() && !controlValue.EqualsWithConversion("false")) { - prependPlus = PR_TRUE; - aAccelString.AppendWithConversion("Ctrl"); - } - - if(!shiftValue.IsEmpty() && !shiftValue.EqualsWithConversion("false")) { + if (!shiftValue.IsEmpty() && !shiftValue.EqualsWithConversion("false")) { if (prependPlus) aAccelString.AppendWithConversion("+"); prependPlus = PR_TRUE; aAccelString.AppendWithConversion("Shift"); } - if (!altValue.IsEmpty() && !altValue.EqualsWithConversion("false")) { - if (prependPlus) - aAccelString.AppendWithConversion("+"); - prependPlus = PR_TRUE; - aAccelString.AppendWithConversion("Alt"); - } - keyChar.ToUpperCase(); if (!keyChar.IsEmpty()) { if (prependPlus) diff --git a/layout/xul/base/src/nsTextBoxFrame.cpp b/layout/xul/base/src/nsTextBoxFrame.cpp index 93f22d658e36..45577c3c3897 100644 --- a/layout/xul/base/src/nsTextBoxFrame.cpp +++ b/layout/xul/base/src/nsTextBoxFrame.cpp @@ -133,10 +133,9 @@ nsTextBoxFrame::Init(nsIPresContext* aPresContext, UpdateAttributes(aPresContext, nsnull, a, b, c /* all */); // the following block is to append the accesskey to to mTitle if there is an accesskey -// but the mTitle doesn't have the character +// but the mTitle doesn't have the character + // XXX Should this code first check to see if there's a menuAccessKey? - -#ifndef XP_UNIX nsAutoString accesskey; mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, accesskey); @@ -163,7 +162,6 @@ nsTextBoxFrame::Init(nsIPresContext* aPresContext, mAccessKeyInfo = nsnull; } } -#endif return rv; } diff --git a/layout/xul/base/src/nsTitledButtonFrame.cpp b/layout/xul/base/src/nsTitledButtonFrame.cpp index 3bc7df387ab7..e4c2167385ed 100644 --- a/layout/xul/base/src/nsTitledButtonFrame.cpp +++ b/layout/xul/base/src/nsTitledButtonFrame.cpp @@ -305,9 +305,9 @@ nsTitledButtonFrame::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? mAccesskeyIndex = -1; -#ifndef XP_UNIX nsAutoString accesskey; mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::accesskey, accesskey); @@ -325,7 +325,6 @@ nsTitledButtonFrame::Init(nsIPresContext* aPresContext, mTitle += tmpstring; } } -#endif return rv; } diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 0ba37c83c5ce..3a1e54fad84d 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -414,6 +414,11 @@ pref("signed.applets.codebase_principal_support", false); pref("security.checkloaduri", true); pref("security.xpconnect.plugin.unrestricted", true); +// Modifier key prefs: default to Windows settings, +// menu access key = alt, accelerator key = control. +pref("ui.key.acceleratorKey", 17); +pref("ui.key.menuAccessKey", 18); + // Middle-mouse handling pref("middlemouse.paste", false); pref("middlemouse.openNewWindow", false); diff --git a/modules/libpref/src/mac/macprefs.js b/modules/libpref/src/mac/macprefs.js index 8c733163c15f..489578fbd6d3 100644 --- a/modules/libpref/src/mac/macprefs.js +++ b/modules/libpref/src/mac/macprefs.js @@ -138,6 +138,9 @@ pref("font.name.monospace.zh-TW", "Apple LiGothic Medium"); pref("font.name.cursive.zh-TW", "XXX.cursive"); pref("font.name.fantasy.zh-TW", "XXX.fantasy"); +// Override the Windows settings: no menu key, meta accelerator key. +pref("ui.key.menuAccessKey", 0); +pref("ui.key.acceleratorKey", 224); // This overrides the setting in config.js (which points to the Windows page) config("menu.help.item_0.label","Help Contents"); diff --git a/rdf/content/src/nsXULKeyListener.cpp b/rdf/content/src/nsXULKeyListener.cpp index 62da8e1c3ace..e11d5983731a 100644 --- a/rdf/content/src/nsXULKeyListener.cpp +++ b/rdf/content/src/nsXULKeyListener.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file @@ -63,6 +63,8 @@ #include "nsIDocumentViewer.h" #include "nsIPresContext.h" #include "nsIDOMEventTarget.h" +#include "nsIPref.h" +#include "nsIServiceManager.h" #include "nsIObserver.h" #include "nsIObserverService.h" @@ -196,6 +198,8 @@ static NS_DEFINE_IID(kIDomNodeIID, NS_IDOMNODE_IID); static NS_DEFINE_IID(kIDomElementIID, NS_IDOMELEMENT_IID); static NS_DEFINE_IID(kIDomEventListenerIID, NS_IDOMEVENTLISTENER_IID); +static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); + enum eEventType { eKeyPress, eKeyDown, @@ -308,10 +312,9 @@ private: static nsSupportsHashtable* mKeyBindingTable; - // The "xul key" modifier can be any of the known modifiers: - enum { - xulKeyNone, xulKeyShift, xulKeyControl, xulKeyAlt, xulKeyMeta - } mXULKeyModifier; + // The "xul key" modifier is a key code from nsIDOMKeyEvent, + // e.g. nsIDOMKeyEvent::DOM_VK_CONTROL + PRUint32 mXULKeyModifier; }; nsSupportsHashtable* nsXULKeyListenerImpl::mKeyBindingTable = nsnull; @@ -461,14 +464,29 @@ nsXULKeyListenerImpl::Init( mDOMDocument = xulDoc; // Weak reference. - // Set the default for the xul key modifier + // Compiled-in defaults, in case we can't get LookAndFeel -- + // command for mac, control for all other platforms. #ifdef XP_MAC - mXULKeyModifier = xulKeyMeta; -#elif XP_UNIX - mXULKeyModifier = xulKeyAlt; + mXULKeyModifier = nsIDOMKeyEvent::DOM_VK_META; #else - mXULKeyModifier = xulKeyControl; + mXULKeyModifier = nsIDOMKeyEvent::DOM_VK_CONTROL; #endif + + // Get the accelerator key value from prefs, overriding the default: + nsresult rv; + NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv); + if (NS_SUCCEEDED(rv) && prefs) + { + rv = prefs->GetIntPref("ui.key.acceleratorKey", + (PRInt32*)&mXULKeyModifier); + } +#ifdef DEBUG_akkana + else + { + NS_ASSERTION(PR_FALSE, "XULKeyListener couldn't get accel key from prefs!\n"); + } +#endif + return NS_OK; } @@ -1478,7 +1496,7 @@ nsXULKeyListenerImpl::HandleEventUsingKeyset(nsIDOMElement* aKeysetElement, nsID || (property == falseString && isModKey)) break; // and also the xul key, if it's specified to be shift: - if (xulKeyShift == mXULKeyModifier && + if (nsIDOMKeyEvent::DOM_VK_SHIFT == mXULKeyModifier && ((xproperty == trueString && !isModKey) || (xproperty == falseString && isModKey))) break; @@ -1491,7 +1509,7 @@ nsXULKeyListenerImpl::HandleEventUsingKeyset(nsIDOMElement* aKeysetElement, nsID || (property == falseString && isModKey)) break; // and if xul is control: - if (xulKeyControl == mXULKeyModifier && + if (nsIDOMKeyEvent::DOM_VK_CONTROL == mXULKeyModifier && ((xproperty == trueString && !isModKey) || (xproperty == falseString && isModKey))) break; @@ -1504,7 +1522,7 @@ nsXULKeyListenerImpl::HandleEventUsingKeyset(nsIDOMElement* aKeysetElement, nsID || (property == falseString && isModKey)) break; // and if xul is alt: - if (xulKeyAlt == mXULKeyModifier && + if (nsIDOMKeyEvent::DOM_VK_ALT == mXULKeyModifier && ((xproperty == trueString && !isModKey) || (xproperty == falseString && isModKey))) break; @@ -1517,7 +1535,7 @@ nsXULKeyListenerImpl::HandleEventUsingKeyset(nsIDOMElement* aKeysetElement, nsID || (property == falseString && isModKey)) break; // and if xul is meta: - if (xulKeyMeta == mXULKeyModifier && + if (nsIDOMKeyEvent::DOM_VK_META == mXULKeyModifier && ((xproperty == trueString && !isModKey) || (xproperty == falseString && isModKey))) break; diff --git a/widget/public/nsGUIEvent.h b/widget/public/nsGUIEvent.h index ce8a6820b507..cfa2ae2f661e 100644 --- a/widget/public/nsGUIEvent.h +++ b/widget/public/nsGUIEvent.h @@ -601,6 +601,8 @@ enum nsDragDropEventStatus { #define NS_VK_CLOSE_BRACKET 0xDD #define NS_VK_QUOTE 0xDE +#define NS_VK_META 0xE0 + #define NS_EVENT_FLAG_NONE 0x0000 #define NS_EVENT_FLAG_INIT 0x0001 #define NS_EVENT_FLAG_BUBBLE 0x0002