Bug 174889 - unable to get keyboard shortcut for treeitem node, r=smaug, ginn.chen, mats, sr=mats, a=sicking

This commit is contained in:
surkov.alexander%gmail.com 2007-08-29 06:52:47 +00:00
Родитель 63092ee320
Коммит 9f86cbcecf
7 изменённых файлов: 163 добавлений и 47 удалений

Просмотреть файл

@ -46,6 +46,9 @@
#include "nsIDOMXULSelectCntrlEl.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIEventListenerManager.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIEventStateManager.h"
#include "nsISelection2.h"
#include "nsISelectionController.h"
@ -176,6 +179,39 @@ nsAccUtils::HasListener(nsIContent *aContent, const nsAString& aEventType)
return listenerManager && listenerManager->HasListenersFor(aEventType);
}
PRUint32
nsAccUtils::GetAccessKeyFor(nsIContent *aContent)
{
if (!aContent)
return 0;
// Accesskeys are registered by @accesskey attribute only. At first check
// whether it is presented on the given element to avoid the slow
// nsIEventStateManager::GetRegisteredAccessKey() method.
if (!aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::accesskey))
return 0;
nsCOMPtr<nsIDocument> doc = aContent->GetOwnerDoc();
if (!doc)
return 0;
nsCOMPtr<nsIPresShell> presShell = doc->GetPrimaryShell();
if (!presShell)
return 0;
nsPresContext *presContext = presShell->GetPresContext();
if (!presContext)
return 0;
nsIEventStateManager *esm = presContext->EventStateManager();
if (!esm)
return 0;
PRUint32 key = 0;
esm->GetRegisteredAccessKey(aContent, &key);
return key;
}
nsresult
nsAccUtils::FireAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
PRBool aIsAsynch)

Просмотреть файл

@ -109,6 +109,14 @@ public:
*/
static PRBool HasListener(nsIContent *aContent, const nsAString& aEventType);
/**
* Return an accesskey registered on the given element by
* nsIEventStateManager or 0 if there is no registered accesskey.
*
* @param aContent - the given element.
*/
static PRUint32 GetAccessKeyFor(nsIContent *aContent);
/**
* Fire accessible event of the given type for the given accessible.
*/

Просмотреть файл

@ -349,7 +349,7 @@ NS_IMETHODIMP nsAccessible::GetDescription(nsAString& aDescription)
// returns the accesskey modifier mask used in the given node's context
// (i.e. chrome or content), or 0 if an error occurs
static PRInt32
GetAccessModifierMask(nsIDOMElement* aDOMNode)
GetAccessModifierMask(nsIContent* aContent)
{
nsCOMPtr<nsIPrefBranch> prefBranch =
do_GetService(NS_PREFSERVICE_CONTRACTID);
@ -370,8 +370,7 @@ GetAccessModifierMask(nsIDOMElement* aDOMNode)
}
// get the docShell to this DOMNode, return 0 on failure
nsCOMPtr<nsIContent> content(do_QueryInterface(aDOMNode));
nsCOMPtr<nsIDocument> document = content->GetCurrentDoc();
nsCOMPtr<nsIDocument> document = aContent->GetCurrentDoc();
if (!document)
return 0;
nsCOMPtr<nsISupports> container = document->GetContainer();
@ -398,47 +397,49 @@ GetAccessModifierMask(nsIDOMElement* aDOMNode)
return NS_SUCCEEDED(rv) ? accessModifierMask : 0;
}
NS_IMETHODIMP nsAccessible::GetKeyboardShortcut(nsAString& _retval)
NS_IMETHODIMP
nsAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
{
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(mDOMNode));
if (elt) {
nsAutoString accesskey;
elt->GetAttribute(NS_LITERAL_STRING("accesskey"), accesskey);
if (accesskey.IsEmpty()) {
nsCOMPtr<nsIContent> content = do_QueryInterface(elt);
nsIContent *labelContent = GetLabelContent(content);
if (labelContent) {
labelContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::accesskey, accesskey);
}
if (accesskey.IsEmpty()) {
return NS_ERROR_FAILURE;
}
}
aAccessKey.Truncate();
// append the modifiers in reverse order
// (result: Control+Alt+Shift+Meta+<key>)
nsAutoString propertyKey;
PRInt32 modifierMask = GetAccessModifierMask(elt);
if (modifierMask & NS_MODIFIER_META) {
propertyKey.AssignLiteral("VK_META");
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
}
if (modifierMask & NS_MODIFIER_SHIFT) {
propertyKey.AssignLiteral("VK_SHIFT");
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
}
if (modifierMask & NS_MODIFIER_ALT) {
propertyKey.AssignLiteral("VK_ALT");
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
}
if (modifierMask & NS_MODIFIER_CONTROL) {
propertyKey.AssignLiteral("VK_CONTROL");
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
}
_retval= accesskey;
return NS_OK;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (!content)
return NS_ERROR_FAILURE;
PRUint32 key = nsAccUtils::GetAccessKeyFor(content);
if (!key) {
nsCOMPtr<nsIContent> labelContent(GetLabelContent(content));
if (labelContent)
key = nsAccUtils::GetAccessKeyFor(labelContent);
}
return NS_ERROR_FAILURE;
if (!key)
return NS_OK;
nsAutoString accesskey(key);
// Append the modifiers in reverse order, result: Control+Alt+Shift+Meta+<key>
nsAutoString propertyKey;
PRInt32 modifierMask = GetAccessModifierMask(content);
if (modifierMask & NS_MODIFIER_META) {
propertyKey.AssignLiteral("VK_META");
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
}
if (modifierMask & NS_MODIFIER_SHIFT) {
propertyKey.AssignLiteral("VK_SHIFT");
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
}
if (modifierMask & NS_MODIFIER_ALT) {
propertyKey.AssignLiteral("VK_ALT");
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
}
if (modifierMask & NS_MODIFIER_CONTROL) {
propertyKey.AssignLiteral("VK_CONTROL");
nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
}
aAccessKey = accesskey;
return NS_OK;
}
NS_IMETHODIMP nsAccessible::SetParent(nsIAccessible *aParent)

Просмотреть файл

@ -391,13 +391,18 @@ NS_IMETHODIMP nsXULMenuitemAccessible::GetDescription(nsAString& aDescription)
}
//return menu accesskey: N or Alt+F
NS_IMETHODIMP nsXULMenuitemAccessible::GetKeyboardShortcut(nsAString& _retval)
NS_IMETHODIMP
nsXULMenuitemAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
{
aAccessKey.Truncate();
static PRInt32 gMenuAccesskeyModifier = -1; // magic value of -1 indicates unitialized state
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(mDOMNode));
if (elt) {
nsAutoString accesskey;
// We do not use nsAccUtils::GetAccesskeyFor() because accesskeys for
// menu are't registered by nsIEventStateManager.
elt->GetAttribute(NS_LITERAL_STRING("accesskey"), accesskey);
if (accesskey.IsEmpty())
return NS_OK;
@ -423,11 +428,11 @@ NS_IMETHODIMP nsXULMenuitemAccessible::GetKeyboardShortcut(nsAString& _retval)
case nsIDOMKeyEvent::DOM_VK_META: propertyKey.AssignLiteral("VK_META"); break;
}
if (!propertyKey.IsEmpty())
nsAccessible::GetFullKeyName(propertyKey, accesskey, _retval);
nsAccessible::GetFullKeyName(propertyKey, accesskey, aAccessKey);
}
}
if (_retval.IsEmpty())
_retval = accesskey;
if (aAccessKey.IsEmpty())
aAccessKey = accesskey;
return NS_OK;
}
return NS_ERROR_FAILURE;

Просмотреть файл

@ -54,8 +54,8 @@ class imgIContainer;
*/
// {fb7516ff-2f01-4893-84e8-e4b282813023}
#define NS_IEVENTSTATEMANAGER_IID \
{ 0xfb7516ff, 0x2f01, 0x4893, \
{ 0x84, 0xe8, 0xe4, 0xb2, 0x82, 0x81, 0x30, 0x23 } }
{ 0x522d12ec, 0xde51, 0x4635, \
{ 0xb0, 0x10, 0x4, 0x2a, 0x6d, 0x5, 0xa0, 0x3e } }
#define NS_EVENT_NEEDS_FRAME(event) (!NS_IS_FOCUS_EVENT(event))
@ -132,9 +132,33 @@ public:
NS_IMETHOD ChangeFocusWith(nsIContent *aFocusContent, EFocusedWithType aFocusedWith) = 0;
// Access Key Registration
/**
* Register accesskey on the given element. When accesskey is activated then
* the element will be notified via nsIContent::PerformAccesskey() method.
*
* @param aContent the given element
* @param aKey accesskey
*/
NS_IMETHOD RegisterAccessKey(nsIContent* aContent, PRUint32 aKey) = 0;
/**
* Unregister accesskey for the given element.
*
* @param aContent the given element
* @param aKey accesskey
*/
NS_IMETHOD UnregisterAccessKey(nsIContent* aContent, PRUint32 aKey) = 0;
/**
* Get accesskey registered on the given element or 0 if there is none.
*
* @param aContent the given element
* @param aKey registered accesskey
* @return NS_OK
*/
NS_IMETHOD GetRegisteredAccessKey(nsIContent* aContent, PRUint32* aKey) = 0;
NS_IMETHOD SetCursor(PRInt32 aCursor, imgIContainer* aContainer,
PRBool aHaveHotspot, float aHotspotX, float aHotspotY,
nsIWidget* aWidget, PRBool aLockCursor) = 0;

Просмотреть файл

@ -179,6 +179,27 @@ enum {
MOUSE_SCROLL_PIXELS
};
struct AccessKeyInfo {
PRUint32 mAccessKey;
nsIContent* mTarget;
AccessKeyInfo(nsIContent* aTarget) : mAccessKey(0), mTarget(aTarget) {}
};
static PRIntn PR_CALLBACK
FindTargetForAccessKey(nsHashKey *aKey, void *aData, void* aClosure)
{
AccessKeyInfo* info = static_cast<AccessKeyInfo*>(aClosure);
nsIContent* aTarget = static_cast<nsIContent*>(aData);
if (aTarget == info->mTarget) {
info->mAccessKey = aKey->HashCode();
return kHashEnumerateStop;
}
return kHashEnumerateNext;
}
// mask values for ui.key.chromeAccess and ui.key.contentAccess
#define NS_MODIFIER_SHIFT 1
#define NS_MODIFIER_CONTROL 2
@ -4659,6 +4680,8 @@ nsEventStateManager::RegisterAccessKey(nsIContent* aContent, PRUint32 aKey)
PRUint32 accKey = (IS_IN_BMP(aKey)) ? ToLowerCase((PRUnichar)aKey) : aKey;
nsVoidKey key(NS_INT32_TO_PTR(accKey));
NS_ASSERTION(key.HashCode() == accKey,
"nsHashKey::HashCode() doesn't return an accesskey");
#ifdef DEBUG_jag
nsCOMPtr<nsIContent> oldContent = dont_AddRef(static_cast<nsIContent*>(mAccessKeys->Get(&key)));
@ -4694,6 +4717,24 @@ nsEventStateManager::UnregisterAccessKey(nsIContent* aContent, PRUint32 aKey)
return NS_OK;
}
NS_IMETHODIMP
nsEventStateManager::GetRegisteredAccessKey(nsIContent* aContent,
PRUint32* aKey)
{
NS_ENSURE_ARG(aContent);
NS_ENSURE_ARG_POINTER(aKey);
*aKey = 0;
if (!mAccessKeys)
return NS_OK;
AccessKeyInfo info(aContent);
mAccessKeys->Enumerate(FindTargetForAccessKey, &info);
*aKey = info.mAccessKey;
return NS_OK;
}
void
nsEventStateManager::ForceViewUpdate(nsIView* aView)
{

Просмотреть файл

@ -127,6 +127,7 @@ public:
// Access Key Registration
NS_IMETHOD RegisterAccessKey(nsIContent* aContent, PRUint32 aKey);
NS_IMETHOD UnregisterAccessKey(nsIContent* aContent, PRUint32 aKey);
NS_IMETHOD GetRegisteredAccessKey(nsIContent* aContent, PRUint32* aKey);
NS_IMETHOD SetCursor(PRInt32 aCursor, imgIContainer* aContainer,
PRBool aHaveHotspot, float aHotspotX, float aHotspotY,