Bug 136696. Active Accessibility: support get_accKeyboardShortcut(). r=jgaunt, sr=jst

This commit is contained in:
aaronl%netscape.com 2002-05-08 20:43:49 +00:00
parent c66cdd4fe6
commit a97fef7f68
17 changed files with 192 additions and 44 deletions

View File

@ -42,6 +42,8 @@ interface nsIAccessible : nsISupports
readonly attribute DOMString accValue;
readonly attribute DOMString accDescription;
readonly attribute DOMString accKeyboardShortcut;
readonly attribute unsigned long accRole;
readonly attribute unsigned long accState;
readonly attribute unsigned long accExtState;

View File

@ -41,6 +41,7 @@ REQUIRES = \
layout \
locale \
necko \
pref \
string \
uriloader \
view \

View File

@ -32,6 +32,7 @@ REQUIRES = \
layout \
locale \
necko \
pref \
string \
uriloader \
view \

View File

@ -62,7 +62,6 @@
#include "nsISelection.h"
#include "nsISelectionController.h"
#include "nsIServiceManager.h"
#include "nsIStringBundle.h"
#include "nsXPIDLString.h"
#include "nsIDOMComment.h"
@ -97,6 +96,7 @@
#include "nsIDOMXULSelectCntrlEl.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsString.h"
#include "nsIPref.h"
// IFrame Helpers
#include "nsIDocShell.h"
@ -111,11 +111,13 @@
#include "nsIDOMCharacterData.h"
#endif
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
//#define DEBUG_LEAKS
#ifdef DEBUG_LEAKS
static gnsAccessibles = 0;
#endif
PRUint32 nsAccessible::gInstanceCount = 0;
nsIStringBundle *nsAccessible::gStringBundle = 0;
nsIStringBundle *nsAccessible::gKeyStringBundle = 0;
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
@ -448,9 +450,21 @@ nsAccessible::nsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell): mDOMNod
}
#endif
++gInstanceCount;
#ifdef DEBUG_LEAKS
printf("nsAccessibles=%d\n", ++gnsAccessibles);
printf("nsAccessibles=%d\n", gInstanceCount);
#endif
if (gInstanceCount == 1) {
nsresult rv;
nsCOMPtr<nsIStringBundleService> stringBundleService(do_GetService(kStringBundleServiceCID, &rv));
if (stringBundleService) {
stringBundleService->CreateBundle(ACCESSIBLE_BUNDLE_URL, &gStringBundle);
NS_IF_ADDREF(gStringBundle);
stringBundleService->CreateBundle(PLATFORM_KEYS_BUNDLE_URL, &gKeyStringBundle);
NS_IF_ADDREF(gKeyStringBundle);
}
}
}
//-----------------------------------------------------
@ -458,8 +472,13 @@ nsAccessible::nsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell): mDOMNod
//-----------------------------------------------------
nsAccessible::~nsAccessible()
{
if (--gInstanceCount == 0) {
NS_IF_RELEASE(gStringBundle);
NS_IF_RELEASE(gKeyStringBundle);
}
#ifdef DEBUG_LEAKS
printf("nsAccessibles=%d\n", --gnsAccessibles);
printf("nsAccessibles=%d\n", gInstanceCount);
#endif
}
@ -472,6 +491,39 @@ NS_IMETHODIMP nsAccessible::GetAccName(nsAString& _retval)
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsAccessible::GetAccKeyboardShortcut(nsAString& _retval)
{
static PRInt32 gGeneralAccesskeyModifier = -1; // magic value of -1 indicates unitialized state
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(mDOMNode));
if (elt) {
nsAutoString accesskey;
elt->GetAttribute(NS_LITERAL_STRING("accesskey"), accesskey);
if (accesskey.IsEmpty())
return NS_OK;
if (gGeneralAccesskeyModifier == -1) { // Need to initialize cached global accesskey pref
gGeneralAccesskeyModifier = 0;
nsresult result;
nsCOMPtr<nsIPref> prefService(do_GetService(kPrefCID, &result));
if (NS_SUCCEEDED(result) && prefService)
prefService->GetIntPref("ui.key.generalAccessKey", &gGeneralAccesskeyModifier);
}
nsAutoString propertyKey;
switch (gGeneralAccesskeyModifier) {
case nsIDOMKeyEvent::DOM_VK_CONTROL: propertyKey = NS_LITERAL_STRING("VK_CONTROL"); break;
case nsIDOMKeyEvent::DOM_VK_ALT: propertyKey = NS_LITERAL_STRING("VK_ALT"); break;
case nsIDOMKeyEvent::DOM_VK_META: propertyKey = NS_LITERAL_STRING("VK_META"); break;
}
if (!propertyKey.IsEmpty())
nsAccessible::GetFullKeyName(propertyKey, accesskey, _retval);
else
_retval= accesskey;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsAccessible::CacheOptimizations(nsIAccessible *aParent, PRInt32 aSiblingIndex, nsIDOMNodeList *aSiblingList)
{
if (aParent)
@ -577,30 +629,32 @@ NS_IMETHODIMP nsAccessible::GetAccChildCount(PRInt32 *aAccChildCount)
nsresult nsAccessible::GetTranslatedString(const nsAString& aKey, nsAString& aStringOut)
{
static nsCOMPtr<nsIStringBundle> stringBundle;
static PRBool firstTime = PR_TRUE;
if (firstTime) {
firstTime = PR_FALSE;
nsresult rv;
nsCOMPtr<nsIStringBundleService> stringBundleService =
do_GetService(kStringBundleServiceCID, &rv);
if (!stringBundleService) {
NS_WARNING("ERROR: Failed to get StringBundle Service instance.\n");
return NS_ERROR_FAILURE;
}
stringBundleService->CreateBundle(ACCESSIBLE_BUNDLE_URL, getter_AddRefs(stringBundle));
}
nsXPIDLString xsValue;
if (!stringBundle ||
NS_FAILED(stringBundle->GetStringFromName(PromiseFlatString(aKey).get(), getter_Copies(xsValue))))
if (!gStringBundle ||
NS_FAILED(gStringBundle->GetStringFromName(PromiseFlatString(aKey).get(), getter_Copies(xsValue))))
return NS_ERROR_FAILURE;
aStringOut.Assign(xsValue);
return NS_OK;
}
nsresult nsAccessible::GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut)
{
nsXPIDLString modifierName, separator;
if (!gKeyStringBundle ||
NS_FAILED(gKeyStringBundle->GetStringFromName(PromiseFlatString(aModifierName).get(),
getter_Copies(modifierName))) ||
NS_FAILED(gKeyStringBundle->GetStringFromName(PromiseFlatString(NS_LITERAL_STRING("MODIFIER_SEPARATOR")).get(),
getter_Copies(separator)))) {
return NS_ERROR_FAILURE;
}
aStringOut = modifierName + separator + aKeyName;
return NS_OK;
}
PRBool nsAccessible::IsPartiallyVisible()
{
// We need to know if at least a kMinPixels around the object is visible

View File

@ -53,8 +53,10 @@
#include "nsWeakReference.h"
#include "nsIDOMNodeList.h"
#include "nsIBindingManager.h"
#include "nsIStringBundle.h"
#define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties"
#define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties"
class nsIContent;
class nsIDocShell;
@ -75,6 +77,7 @@ public:
virtual ~nsAccessible();
NS_IMETHOD GetAccName(nsAString& _retval);
NS_IMETHOD GetAccKeyboardShortcut(nsAString& _retval);
NS_IMETHOD GetAccParent(nsIAccessible **_retval);
NS_IMETHOD GetAccNextSibling(nsIAccessible **_retval);
NS_IMETHOD GetAccPreviousSibling(nsIAccessible **_retval);
@ -107,6 +110,8 @@ protected:
NS_IMETHOD CacheOptimizations(nsIAccessible *aParent, PRInt32 aSiblingIndex, nsIDOMNodeList *aSiblingList);
// helper method to verify frames
static PRBool IsCorrectFrameType(nsIFrame* aFrame, nsIAtom* aAtom);
static nsresult InitStringBundleService();
static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut);
void GetScrollOffset(nsRect *aRect);
void GetScreenOrigin(nsIPresContext *aPresContext, nsIFrame *aFrame, nsRect *aRect);
@ -117,6 +122,10 @@ protected:
nsCOMPtr<nsIAccessible> mParent;
nsCOMPtr<nsIDOMNodeList> mSiblingList; // If some of our computed siblings are anonymous content nodes, cache node list
PRInt32 mSiblingIndex; // Cache where we are in list of kids that we got from nsIBindingManager::GetContentList(parentContent)
static PRUint32 gInstanceCount;
static nsIStringBundle *gStringBundle;
static nsIStringBundle *gKeyStringBundle;
};

View File

@ -93,37 +93,43 @@ NS_IMETHODIMP nsGenericAccessible::GetAccChildCount(PRInt32 *_retval)
return NS_ERROR_NOT_IMPLEMENTED;
}
/* wstring getAccName (); */
/* DOMString getAccName (); */
NS_IMETHODIMP nsGenericAccessible::GetAccName(nsAString& _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* wstring getAccValue (); */
/* DOMString getAccValue (); */
NS_IMETHODIMP nsGenericAccessible::GetAccValue(nsAString& _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void setAccName (in wstring name); */
/* void setAccName (in DOMString name); */
NS_IMETHODIMP nsGenericAccessible::SetAccName(const nsAString& name)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* wstring getAccDescription (); */
/* DOMString getAccDescription (); */
NS_IMETHODIMP nsGenericAccessible::GetAccDescription(nsAString& _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* DOMString getAccKeyboardShortcut (); */
NS_IMETHODIMP nsGenericAccessible::GetAccKeyboardShortcut(nsAString& _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* unsigned long getAccRole (); */
NS_IMETHODIMP nsGenericAccessible::GetAccRole(PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* wstring getAccState (); */
/* DOMString getAccState (); */
NS_IMETHODIMP nsGenericAccessible::GetAccState(PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
@ -135,7 +141,7 @@ NS_IMETHODIMP nsGenericAccessible::GetAccNumActions(PRUint8 *_retval)
return NS_ERROR_NOT_IMPLEMENTED;
}
/* wstring getAccActionName (in PRUint8 index); */
/* DOMString getAccActionName (in PRUint8 index); */
NS_IMETHODIMP nsGenericAccessible::GetAccActionName(PRUint8 index, nsAString& _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
@ -153,7 +159,7 @@ NS_IMETHODIMP nsGenericAccessible::GetAccFocused(nsIAccessible **_retval)
return NS_ERROR_NOT_IMPLEMENTED;
}
/* wstring getAccHelp (); */
/* DOMString getAccHelp (); */
NS_IMETHODIMP nsGenericAccessible::GetAccHelp(nsAString& _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;

View File

@ -29,6 +29,7 @@ REQUIRES = \
gfx2 \
htmlparser \
imglib2 \
intl \
layout \
locale \
necko \

View File

@ -41,6 +41,7 @@ REQUIRES = \
layout \
locale \
necko \
pref \
string \
uriloader \
view \

View File

@ -26,8 +26,10 @@ REQUIRES = \
content \
dom \
gfx \
intl \
layout \
necko \
pref \
string \
widget \
xpcom \

View File

@ -43,6 +43,11 @@
#include "nsIDOMElement.h"
#include "nsIDOMXULElement.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIDOMKeyEvent.h"
#include "nsIPref.h"
#include "nsIServiceManager.h"
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
// ------------------------ Menu Item -----------------------------
@ -110,6 +115,48 @@ NS_IMETHODIMP nsXULMenuitemAccessible::GetAccName(nsAString& _retval)
return NS_OK;
}
NS_IMETHODIMP nsXULMenuitemAccessible::GetAccKeyboardShortcut(nsAString& _retval)
{
static PRInt32 gMenuAccesskeyModifier = -1; // magic value of -1 indicates unitialized state
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(mDOMNode));
if (elt) {
nsAutoString accesskey;
elt->GetAttribute(NS_LITERAL_STRING("accesskey"), accesskey);
if (accesskey.IsEmpty())
return NS_OK;
nsCOMPtr<nsIAccessible> parentAccessible;
GetAccParent(getter_AddRefs(parentAccessible));
if (parentAccessible) {
PRUint32 role;
parentAccessible->GetAccRole(&role);
if (role == ROLE_MENUBAR) {
// If top level menu item, add Alt+ or whatever modifier text to string
// No need to cache pref service, this happens rarely
if (gMenuAccesskeyModifier == -1) { // Need to initialize cached global accesskey pref
gMenuAccesskeyModifier = 0;
nsresult result;
nsCOMPtr<nsIPref> prefService(do_GetService(kPrefCID, &result));
if (NS_SUCCEEDED(result) && prefService)
prefService->GetIntPref("ui.key.menuAccessKey", &gMenuAccesskeyModifier);
}
nsAutoString propertyKey;
switch (gMenuAccesskeyModifier) {
case nsIDOMKeyEvent::DOM_VK_CONTROL: propertyKey = NS_LITERAL_STRING("VK_CONTROL"); break;
case nsIDOMKeyEvent::DOM_VK_ALT: propertyKey = NS_LITERAL_STRING("VK_ALT"); break;
case nsIDOMKeyEvent::DOM_VK_META: propertyKey = NS_LITERAL_STRING("VK_META"); break;
}
if (!propertyKey.IsEmpty())
nsAccessible::GetFullKeyName(propertyKey, accesskey, _retval);
}
}
if (_retval.IsEmpty())
_retval = accesskey;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsXULMenuitemAccessible::GetAccRole(PRUint32 *_retval)
{

View File

@ -50,6 +50,7 @@ class nsXULMenuitemAccessible : public nsAccessible
public:
nsXULMenuitemAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
NS_IMETHOD GetAccName(nsAString& _retval);
NS_IMETHOD GetAccKeyboardShortcut(nsAString& _retval);
NS_IMETHOD GetAccState(PRUint32 *_retval);
NS_IMETHOD GetAccRole(PRUint32 *_retval);
NS_IMETHOD GetAccFirstChild(nsIAccessible **aAccFirstChild);

View File

@ -62,8 +62,8 @@
* - nsXULComboboxAccessible <menulist />
* - nsHTMLTextFieldAccessible
* - nsXULComboboxButtonAccessible
* - nsXULSelectListAccessible <menupopup />
* - nsXULSelectOptionAccessible(s) <menuitem />
* - nsXULSelectListAccessible <menupopup />
* - nsXULSelectOptionAccessible(s) <menuitem />
*/
/** ------------------------------------------------------ */

View File

@ -89,6 +89,7 @@
#include "nsXULAtoms.h"
#include "nsIDOMXULElement.h"
#include "nsIDOMXULDocument.h"
#include "nsIDOMKeyEvent.h"
#include "nsIObserverService.h"
#include "nsIDocShell.h"
#include "nsIMarkupDocumentViewer.h"
@ -139,6 +140,7 @@ nsIDocument * gLastFocusedDocument = 0; // Strong reference
nsIPresContext* gLastFocusedPresContext = 0; // Weak reference
PRUint32 nsEventStateManager::mInstanceCount = 0;
PRInt32 nsEventStateManager::gGeneralAccesskeyModifier = -1; // magic value of -1 means uninitialized
enum {
MOUSE_SCROLL_N_LINES,
@ -210,6 +212,8 @@ nsEventStateManager::Init()
if (NS_SUCCEEDED(rv)) {
mPrefService->GetBoolPref("nglayout.events.dispatchLeftClickOnly", &mLeftClickOnly);
if (nsEventStateManager::gGeneralAccesskeyModifier == -1) // magic value of -1 means uninitialized
mPrefService->GetIntPref("ui.key.generalAccessKey", &nsEventStateManager::gGeneralAccesskeyModifier);
}
return rv;
@ -762,18 +766,17 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext,
{
nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
#if defined(XP_MAC) || defined(XP_MACOSX)
// (pinkerton, joki, saari) IE5 for mac uses Control for access keys. The HTML4 spec
// suggests to use command on mac, but this really sucks (imagine someone having a "q"
// as an access key and not letting you quit the app!). As a result, we've made a
// command decision 1 day before tree lockdown to change it to the control key.
PRBool isSpecialAccessKeyDown = keyEvent->isControl;
#else
PRBool isSpecialAccessKeyDown = keyEvent->isAlt;
#endif
//This is to prevent keyboard scrolling while alt modifier in use.
PRBool isSpecialAccessKeyDown = PR_FALSE;
switch (gGeneralAccesskeyModifier) {
case nsIDOMKeyEvent::DOM_VK_CONTROL: isSpecialAccessKeyDown = keyEvent->isControl; break;
case nsIDOMKeyEvent::DOM_VK_ALT: isSpecialAccessKeyDown = keyEvent->isAlt; break;
case nsIDOMKeyEvent::DOM_VK_META: isSpecialAccessKeyDown = keyEvent->isMeta; break;
}
//This is to prevent keyboard scrolling while alt or other accesskey modifier in use.
if (isSpecialAccessKeyDown) {
//Alt key is down, we may need to do an accesskey
//Alt or other accesskey modifier is down, we may need to do an accesskey
if (mAccessKeys) {
//Someone registered an accesskey. Find and activate it.
PRUnichar accKey = nsCRT::ToLower((char)keyEvent->charCode);

View File

@ -255,6 +255,7 @@ protected:
nsSupportsHashtable *mAccessKeys;
static PRUint32 mInstanceCount;
static PRInt32 gGeneralAccesskeyModifier;
// For preferences handling
nsCOMPtr<nsIPref> mPrefService;

View File

@ -592,7 +592,9 @@ pref("security.xpconnect.plugin.unrestricted", true);
// Modifier key prefs: default to Windows settings,
// menu access key = alt, accelerator key = control.
// Use 17 for Ctrl, 18 for Alt, 224 for Meta, 0 for none. Mac settings in macprefs.js
pref("ui.key.accelKey", 17);
pref("ui.key.generalAccessKey", 18);
pref("ui.key.menuAccessKey", 18);
pref("ui.key.menuAccessKeyFocuses", false);
pref("ui.key.saveLink.shift", true); // true = shift, false = meta

View File

@ -180,9 +180,15 @@ pref("font.size.fixed.zh-CN", 16);
pref("font.size.variable.zh-TW", 16);
pref("font.size.fixed.zh-TW", 16);
// Override the Windows settings: no menu key, meta accelerator key.
// Override the Windows settings: no menu key, meta accelerator key. ctrl for general access key in HTML/XUL
// Use 17 for Ctrl, 18 for Option, 224 for Cmd, 0 for none
pref("ui.key.menuAccessKey", 0);
pref("ui.key.accelKey", 224);
// (pinkerton, joki, saari) IE5 for mac uses Control for access keys. The HTML4 spec
// suggests to use command on mac, but this really sucks (imagine someone having a "q"
// as an access key and not letting you quit the app!). As a result, we've made a
// command decision 1 day before tree lockdown to change it to the control key.
pref("ui.key.generalAccessKey", 17);
// print_extra_margin enables platforms to specify an extra gap or margin
// around the content of the page for Print Preview only

View File

@ -422,6 +422,17 @@ STDMETHODIMP Accessible::get_accKeyboardShortcut(
/* [retval][out] */ BSTR __RPC_FAR *pszKeyboardShortcut)
{
*pszKeyboardShortcut = NULL;
nsCOMPtr<nsIAccessible> a;
GetNSAccessibleFor(varChild,a);
if (a) {
nsAutoString shortcut;
nsresult rv = a->GetAccKeyboardShortcut(shortcut);
if (NS_FAILED(rv))
return S_FALSE;
*pszKeyboardShortcut = ::SysAllocString(shortcut.get());
return S_OK;
}
return S_FALSE;
}