Bug 344896. Refactor accessibility events handling. Part 1 of fix, add nsPIAccessible::allowsAnonChildAccessibles(). Patch by Alexander Surkov. r=aaronlev

This commit is contained in:
aaronleventhal%moonset.net 2006-07-26 19:38:25 +00:00
Родитель 8b65ce02b5
Коммит 6fcd778854
23 изменённых файлов: 107 добавлений и 54 удалений

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

@ -52,4 +52,11 @@ interface nsPIAccessible : nsISupports
*/
[noscript] void invalidateChildren();
[noscript] void fireToolkitEvent(in unsigned long aEvent, in nsIAccessible aTarget, in voidPtr aData);
/**
* Return true if there are accessible children in anonymous content
*/
[noscript] readonly attribute boolean allowsAnonChildAccessibles;
};

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

@ -76,10 +76,22 @@ PRBool nsAccessNode::gIsAccessibilityActive = PR_FALSE;
PRBool nsAccessNode::gIsCacheDisabled = PR_FALSE;
nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> nsAccessNode::gGlobalDocAccessibleCache;
nsIAccessibilityService *nsAccessNode::sAccService = nsnull;
nsIAccessibilityService *nsAccessNode::GetAccService()
{
if (!sAccService) {
nsresult rv = CallGetService("@mozilla.org/accessibilityService;1",
&sAccService);
NS_ASSERTION(NS_SUCCEEDED(rv), "No accessibility service");
}
return sAccService;
}
/*
* Class nsAccessNode
*/
//-----------------------------------------------------
// construction
//-----------------------------------------------------
@ -120,13 +132,11 @@ NS_IMETHODIMP nsAccessNode::Init()
if (presShell) {
nsCOMPtr<nsIDOMNode> docNode(do_QueryInterface(presShell->GetDocument()));
if (docNode) {
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
NS_ASSERTION(accService, "No accessibility service");
nsIAccessibilityService *accService = GetAccService();
if (accService) {
nsCOMPtr<nsIAccessible> accessible;
accService->GetAccessibleInShell(docNode, presShell,
getter_AddRefs(accessible));
accService->GetAccessibleInShell(docNode, presShell,
getter_AddRefs(accessible));
docAccessible = do_QueryInterface(accessible);
}
}
@ -212,6 +222,7 @@ void nsAccessNode::ShutdownXPAccessibility()
NS_IF_RELEASE(gKeyStringBundle);
NS_IF_RELEASE(gDoCommandTimer);
NS_IF_RELEASE(gLastFocusedNode);
NS_IF_RELEASE(sAccService);
ClearCache(gGlobalDocAccessibleCache);
@ -339,8 +350,7 @@ nsAccessNode::GetInnerHTML(nsAString& aInnerHTML)
nsresult
nsAccessNode::MakeAccessNode(nsIDOMNode *aNode, nsIAccessNode **aAccessNode)
{
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
nsIAccessibilityService *accService = GetAccService();
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
nsCOMPtr<nsIAccessNode> accessNode;
@ -348,9 +358,9 @@ nsAccessNode::MakeAccessNode(nsIDOMNode *aNode, nsIAccessNode **aAccessNode)
if (!accessNode) {
nsCOMPtr<nsIAccessible> accessible;
accService->GetAccessibleInWeakShell(aNode, mWeakShell,
accService->GetAccessibleInWeakShell(aNode, mWeakShell,
getter_AddRefs(accessible));
accessNode = do_QueryInterface(accessible);
}

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

@ -54,6 +54,7 @@
#include "nsIStringBundle.h"
#include "nsWeakReference.h"
#include "nsInterfaceHashtable.h"
#include "nsIAccessibilityService.h"
class nsIPresShell;
class nsPresContext;
@ -146,6 +147,7 @@ class nsAccessNode: public nsIAccessNode, public nsPIAccessNode
already_AddRefed<nsRootAccessible> GetRootAccessible();
static nsIDOMNode *gLastFocusedNode;
static nsIAccessibilityService* GetAccService();
protected:
nsresult MakeAccessNode(nsIDOMNode *aNode, nsIAccessNode **aAccessNode);
@ -168,6 +170,9 @@ protected:
static PRBool gIsCacheDisabled;
static nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> gGlobalDocAccessibleCache;
private:
static nsIAccessibilityService *sAccService;
};
#endif

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

@ -642,7 +642,7 @@ nsIAccessible *nsAccessible::NextChild(nsCOMPtr<nsIAccessible>& aAccessible)
return (aAccessible = nextChild);
}
void nsAccessible::CacheChildren(PRBool aWalkAnonContent)
void nsAccessible::CacheChildren()
{
if (!mWeakShell) {
// This node has been shut down
@ -651,7 +651,9 @@ void nsAccessible::CacheChildren(PRBool aWalkAnonContent)
}
if (mAccChildCount == eChildCountUninitialized) {
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, aWalkAnonContent);
PRBool allowsAnonChildren = PR_FALSE;
GetAllowsAnonChildAccessibles(&allowsAnonChildren);
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren);
// Seed the frame hint early while we're still on a container node.
// This is better than doing the GetPrimaryFrameFor() later on
// a text node, because text nodes aren't in the frame map.
@ -672,10 +674,16 @@ void nsAccessible::CacheChildren(PRBool aWalkAnonContent)
}
}
NS_IMETHODIMP nsAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
{
*aAllowsAnonChildren = PR_TRUE;
return NS_OK;
}
/* readonly attribute long childCount; */
NS_IMETHODIMP nsAccessible::GetChildCount(PRInt32 *aAccChildCount)
{
CacheChildren(PR_TRUE);
CacheChildren();
*aAccChildCount = mAccChildCount;
return NS_OK;
}

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

@ -187,7 +187,7 @@ protected:
nsresult AppendFlatStringFromSubtreeRecurse(nsIContent *aContent, nsAString *aFlatString);
// Helpers for dealing with children
virtual void CacheChildren(PRBool aWalkAnonContent);
virtual void CacheChildren();
nsIAccessible *NextChild(nsCOMPtr<nsIAccessible>& aAccessible);
already_AddRefed<nsIAccessible> GetNextWithState(nsIAccessible *aStart, PRUint32 matchState);

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

@ -87,7 +87,7 @@ NS_IMETHODIMP nsOuterDocAccessible::GetState(PRUint32 *aState)
return NS_OK;
}
void nsOuterDocAccessible::CacheChildren(PRBool aWalkAnonContent)
void nsOuterDocAccessible::CacheChildren()
{
// An outer doc accessible usually has 1 nsDocAccessible child,
// but could have none if we can't get to the inner documnet

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

@ -55,7 +55,7 @@ class nsOuterDocAccessible : public nsAccessibleWrap
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *aState);
void CacheChildren(PRBool aWalkAnonContent);
void CacheChildren();
};
#endif

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

@ -104,8 +104,7 @@ NS_IMPL_RELEASE_INHERITED(nsRootAccessible, nsDocAccessible)
// construction
//-----------------------------------------------------
nsRootAccessible::nsRootAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
nsDocAccessibleWrap(aDOMNode, aShell),
mAccService(do_GetService("@mozilla.org/accessibilityService;1")),
nsDocAccessibleWrap(aDOMNode, aShell),
mIsInDHTMLMenu(PR_FALSE)
{
}
@ -348,8 +347,6 @@ nsresult nsRootAccessible::RemoveEventListeners()
mCaretAccessible = nsnull;
}
mAccService = nsnull;
return nsDocAccessible::RemoveEventListeners();
}
@ -591,16 +588,20 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
return NS_OK;
}
nsIAccessibilityService *accService = GetAccService();
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
if (eventType.EqualsLiteral("TreeViewChanged")) {
NS_ENSURE_TRUE(localName.EqualsLiteral("tree"), NS_OK);
nsCOMPtr<nsIContent> treeContent = do_QueryInterface(targetNode);
return mAccService->InvalidateSubtreeFor(eventShell, treeContent,
nsIAccessibleEvent::EVENT_REORDER);
return accService->InvalidateSubtreeFor(eventShell, treeContent,
nsIAccessibleEvent::EVENT_REORDER);
}
nsCOMPtr<nsIAccessible> accessible;
if (NS_FAILED(mAccService->GetAccessibleInShell(targetNode, eventShell,
getter_AddRefs(accessible))))
if (NS_FAILED(accService->GetAccessibleInShell(targetNode, eventShell,
getter_AddRefs(accessible))))
return NS_OK;
#ifdef MOZ_XUL
@ -711,7 +712,7 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
}
if (!targetNode ||
NS_FAILED(mAccService->GetAccessibleInShell(targetNode, eventShell,
NS_FAILED(accService->GetAccessibleInShell(targetNode, eventShell,
getter_AddRefs(accessible)))) {
return NS_OK;
}
@ -936,7 +937,6 @@ NS_IMETHODIMP nsRootAccessible::Shutdown()
return NS_OK; // Already shutdown
}
mCaretAccessible = nsnull;
mAccService = nsnull;
if (mFireFocusTimer) {
mFireFocusTimer->Cancel();
mFireFocusTimer = nsnull;

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

@ -40,7 +40,6 @@
#include "nsDocAccessibleWrap.h"
#include "nsHashtable.h"
#include "nsIAccessibilityService.h"
#include "nsIAccessibleDocument.h"
#include "nsIDocument.h"
#include "nsIDOMFocusListener.h"
@ -106,7 +105,6 @@ class nsRootAccessible : public nsDocAccessibleWrap,
void GetChromeEventHandler(nsIDOMEventTarget **aChromeTarget);
already_AddRefed<nsIDocShellTreeItem>
GetContentDocShell(nsIDocShellTreeItem *aStart);
nsCOMPtr<nsIAccessibilityService> mAccService;
nsCOMPtr<nsIAccessibleCaret> mCaretAccessible;
PRPackedBool mIsInDHTMLMenu;
};

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

@ -491,7 +491,7 @@ NS_IMETHODIMP nsHTMLGroupboxAccessible::GetName(nsAString& aName)
return NS_OK;
}
void nsHTMLGroupboxAccessible::CacheChildren(PRBool aWalkAnonContent)
void nsHTMLGroupboxAccessible::CacheChildren()
{
if (!mWeakShell) {
// This node has been shut down
@ -500,7 +500,9 @@ void nsHTMLGroupboxAccessible::CacheChildren(PRBool aWalkAnonContent)
}
if (mAccChildCount == eChildCountUninitialized) {
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, aWalkAnonContent);
PRBool allowsAnonChildren = PR_FALSE;
GetAllowsAnonChildAccessibles(&allowsAnonChildren);
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren);
walker.mState.frame = GetFrame();
mAccChildCount = 0;
walker.GetFirstChild();

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

@ -122,7 +122,7 @@ public:
NS_IMETHOD GetRole(PRUint32 *_retval);
NS_IMETHOD GetState(PRUint32 *_retval);
NS_IMETHOD GetName(nsAString& _retval);
void CacheChildren(PRBool aWalkAnonContent);
void CacheChildren();
};
#endif

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

@ -167,7 +167,7 @@ already_AddRefed<nsIAccessible> nsHTMLImageAccessible::CreateAreaAccessible(PRIn
}
void nsHTMLImageAccessible::CacheChildren(PRBool aWalkAnonContent)
void nsHTMLImageAccessible::CacheChildren()
{
if (!mWeakShell) {
// This node has been shut down

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

@ -57,7 +57,7 @@ public:
NS_IMETHOD GetRole(PRUint32 *_retval);
protected:
virtual void CacheChildren(PRBool aWalkAnonContent);
virtual void CacheChildren();
already_AddRefed<nsIAccessible> CreateAreaAccessible(PRInt32 areaNum);
nsCOMPtr<nsIDOMHTMLMapElement> mMapElement;
};

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

@ -410,7 +410,7 @@ nsHTMLSelectListAccessible::CacheOptSiblings(nsIAccessibilityService *aAccServic
* flat tree under the Select List.
*/
void nsHTMLSelectListAccessible::CacheChildren(PRBool aWalkAnonContent)
void nsHTMLSelectListAccessible::CacheChildren()
{
// Cache the number of <optgroup> and <option> DOM decendents,
// as well as the accessibles for them. Avoid whitespace text nodes.

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

@ -130,7 +130,7 @@ public:
/* ----- nsIAccessible ----- */
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *_retval);
void CacheChildren(PRBool aWalkAnonContent);
void CacheChildren();
protected:
already_AddRefed<nsIAccessible>

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

@ -241,17 +241,19 @@ NS_IMETHODIMP nsHTMLLIAccessible::GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *wid
return NS_OK;
}
void nsHTMLLIAccessible::CacheChildren(PRBool aWalkAnonContent)
void nsHTMLLIAccessible::CacheChildren()
{
if (!mBulletAccessible || !mWeakShell) {
nsAccessibleWrap::CacheChildren(aWalkAnonContent);
nsAccessibleWrap::CacheChildren();
return;
}
if (mAccChildCount == eChildCountUninitialized) {
SetFirstChild(mBulletAccessible);
mAccChildCount = 1;
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, aWalkAnonContent);
PRBool allowsAnonChildren = PR_FALSE;
GetAllowsAnonChildAccessibles(&allowsAnonChildren);
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren);
walker.mState.frame = GetFrame();
walker.GetFirstChild();

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

@ -137,7 +137,7 @@ public:
NS_IMETHOD GetState(PRUint32 *aState) { nsAccessibleWrap::GetState(aState); *aState |= STATE_READONLY; return NS_OK; }
NS_IMETHOD GetName(nsAString& aName) { aName.SetIsVoid(PR_TRUE); return mRoleMapEntry ? nsAccessible::GetName(aName) : NS_OK; }
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
void CacheChildren(PRBool aWalkAnonContent); // Include bullet accessible
void CacheChildren(); // Include bullet accessible
protected:
nsRefPtr<nsHTMLListBulletAccessible> mBulletAccessible;
};

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

@ -157,7 +157,7 @@ NS_IMETHODIMP nsXULButtonAccessible::GetState(PRUint32 *aState)
return NS_OK;
}
void nsXULButtonAccessible::CacheChildren(PRBool aWalkAnonContent)
void nsXULButtonAccessible::CacheChildren()
{
// An XUL button accessible may have 1 child dropmarker accessible
if (!mWeakShell) {
@ -167,7 +167,9 @@ void nsXULButtonAccessible::CacheChildren(PRBool aWalkAnonContent)
if (mAccChildCount == eChildCountUninitialized) {
mAccChildCount = 0;
SetFirstChild(nsnull);
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
PRBool allowsAnonChildren = PR_FALSE;
GetAllowsAnonChildAccessibles(&allowsAnonChildren);
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, allowsAnonChildren);
walker.GetFirstChild();
nsCOMPtr<nsIAccessible> dropMarkerAccessible;
while (walker.mState.accessible) {

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

@ -56,7 +56,7 @@ public:
NS_IMETHOD GetNumActions(PRUint8 *_retval);
NS_IMETHOD GetActionName(PRUint8 index, nsAString& _retval);
NS_IMETHOD DoAction(PRUint8 index);
void CacheChildren(PRBool aWalkAnonContent);
void CacheChildren();
};
class nsXULCheckboxAccessible : public nsFormControlAccessible

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

@ -245,12 +245,19 @@ NS_IMETHODIMP nsXULMenuitemAccessible::GetChildCount(PRInt32 *aAccChildCount)
}
}
// Argument of PR_FALSE indicates we don't walk anonymous children for menuitems
CacheChildren(PR_FALSE);
CacheChildren();
*aAccChildCount = mAccChildCount;
return NS_OK;
}
NS_IMETHODIMP
nsXULMenuitemAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
{
// That indicates we don't walk anonymous children for menuitems
*aAllowsAnonChildren = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsXULMenuitemAccessible::DoAction(PRUint8 index)
{
if (index == eAction_Select) { // default action

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

@ -59,6 +59,7 @@ public:
NS_IMETHOD DoAction(PRUint8 index);
NS_IMETHOD GetActionName(PRUint8 index, nsAString& _retval);
NS_IMETHOD GetNumActions(PRUint8 *_retval);
NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
};
class nsXULMenuSeparatorAccessible : public nsXULMenuitemAccessible

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

@ -632,16 +632,26 @@ NS_IMETHODIMP nsXULComboboxAccessible::GetChildCount(PRInt32 *aAccChildCount)
}
}
nsAutoString boxName;
mDOMNode->GetNodeName(boxName);
if (boxName.Equals(NS_LITERAL_STRING("textbox"))) {
// autocomplete textbox also uses nsXULComboboxAccessible and we need walk anonymous children
CacheChildren(PR_TRUE);
}
else {
// Argument of PR_FALSE indicates we don't walk anonymous children for menuitems
CacheChildren(PR_FALSE);
}
CacheChildren();
*aAccChildCount = mAccChildCount;
return NS_OK;
}
NS_IMETHODIMP
nsXULComboboxAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
{
nsAutoString boxName;
mDOMNode->GetNodeName(boxName);
if (boxName.Equals(NS_LITERAL_STRING("textbox"))) {
// autocomplete textbox also uses nsXULComboboxAccessible and we need walk
// anonymous children
*aAllowsAnonChildren = PR_TRUE;
} else {
// Argument of PR_FALSE indicates we don't walk anonymous children for
// menuitems
*aAllowsAnonChildren = PR_FALSE;
}
return NS_OK;
}

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

@ -182,6 +182,7 @@ public:
NS_IMETHOD GetValue(nsAString& _retval);
NS_IMETHOD GetDescription(nsAString& aDescription);
NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
};
#endif