bug 427841 - TreeViewChanged event fired on a particular tree table more than once breaks that table's AT-SPI hierarchy, patch by Alexander Surkov <surkov.alexander@gmail.com>, r=evan.yan
This commit is contained in:
Родитель
458d1f6305
Коммит
38408ae1a2
|
@ -47,7 +47,7 @@ interface nsIAccessible;
|
||||||
*
|
*
|
||||||
* @status UNDER_REVIEW
|
* @status UNDER_REVIEW
|
||||||
*/
|
*/
|
||||||
[uuid(7e0f50b0-6444-4372-b00f-4ce81c6b058a)]
|
[uuid(1dde5c3b-bede-43d1-aabf-dabc461113bd)]
|
||||||
interface nsIAccessibleTreeCache : nsISupports
|
interface nsIAccessibleTreeCache : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -82,6 +82,12 @@ interface nsIAccessibleTreeCache : nsISupports
|
||||||
*/
|
*/
|
||||||
void treeViewInvalidated(in long aStartRow, in long aEndRow,
|
void treeViewInvalidated(in long aStartRow, in long aEndRow,
|
||||||
in long aStartCol, in long aEndCol);
|
in long aStartCol, in long aEndCol);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates children created for previous tree view.
|
||||||
|
*/
|
||||||
|
void treeViewChanged();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[uuid(b71532f9-53b2-4647-a5b2-1c5f57e9aed6)]
|
[uuid(b71532f9-53b2-4647-a5b2-1c5f57e9aed6)]
|
||||||
|
|
|
@ -1102,12 +1102,18 @@ nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
|
||||||
nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
|
nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return FirePlatformEvent(aEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsAccessibleWrap::FirePlatformEvent(nsIAccessibleEvent *aEvent)
|
||||||
|
{
|
||||||
nsCOMPtr<nsIAccessible> accessible;
|
nsCOMPtr<nsIAccessible> accessible;
|
||||||
aEvent->GetAccessible(getter_AddRefs(accessible));
|
aEvent->GetAccessible(getter_AddRefs(accessible));
|
||||||
NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
PRUint32 type = 0;
|
PRUint32 type = 0;
|
||||||
rv = aEvent->GetEventType(&type);
|
nsresult rv = aEvent->GetEventType(&type);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
AtkObject *atkObj = nsAccessibleWrap::GetAtkObject(accessible);
|
AtkObject *atkObj = nsAccessibleWrap::GetAtkObject(accessible);
|
||||||
|
|
|
@ -116,6 +116,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual nsresult FirePlatformEvent(nsIAccessibleEvent *aEvent);
|
||||||
|
|
||||||
nsresult FireAtkStateChangeEvent(nsIAccessibleEvent *aEvent,
|
nsresult FireAtkStateChangeEvent(nsIAccessibleEvent *aEvent,
|
||||||
AtkObject *aObject);
|
AtkObject *aObject);
|
||||||
nsresult FireAtkTextChangedEvent(nsIAccessibleEvent *aEvent,
|
nsresult FireAtkTextChangedEvent(nsIAccessibleEvent *aEvent,
|
||||||
|
|
|
@ -246,6 +246,16 @@ protected:
|
||||||
*/
|
*/
|
||||||
nsresult GetAttrValue(nsIAtom *aAriaProperty, double *aValue);
|
nsresult GetAttrValue(nsIAtom *aAriaProperty, double *aValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires platform accessible event. It's notification method only. It does
|
||||||
|
* change nothing on Gecko side. Mostly you should use
|
||||||
|
* nsIAccessible::FireAccessibleEvent excepting special cases like we have
|
||||||
|
* in xul:tree accessible to lie to AT. Must be overridden in wrap classes.
|
||||||
|
*
|
||||||
|
* @param aEvent the accessible event to fire.
|
||||||
|
*/
|
||||||
|
virtual nsresult FirePlatformEvent(nsIAccessibleEvent *aEvent) = 0;
|
||||||
|
|
||||||
// Data Members
|
// Data Members
|
||||||
nsCOMPtr<nsIAccessible> mParent;
|
nsCOMPtr<nsIAccessible> mParent;
|
||||||
nsIAccessible *mFirstChild, *mNextSibling;
|
nsIAccessible *mFirstChild, *mNextSibling;
|
||||||
|
|
|
@ -643,18 +643,6 @@ nsresult nsRootAccessible::HandleEventWithTarget(nsIDOMEvent* aEvent,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
|
||||||
if (eventType.EqualsLiteral("TreeViewChanged")) { // Always asynch, always from user input
|
|
||||||
if (!isTree)
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> treeContent = do_QueryInterface(aTargetNode);
|
|
||||||
nsAccEvent::PrepareForEvent(aTargetNode, PR_TRUE);
|
|
||||||
return accService->InvalidateSubtreeFor(eventShell, treeContent,
|
|
||||||
nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (eventType.EqualsLiteral("popuphiding")) {
|
if (eventType.EqualsLiteral("popuphiding")) {
|
||||||
// If accessible focus was on or inside popup that closes,
|
// If accessible focus was on or inside popup that closes,
|
||||||
// then restore it to true current focus.
|
// then restore it to true current focus.
|
||||||
|
@ -678,11 +666,22 @@ nsresult nsRootAccessible::HandleEventWithTarget(nsIDOMEvent* aEvent,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
if (eventType.EqualsLiteral("TreeRowCountChanged"))
|
if (isTree) {
|
||||||
return HandleTreeRowCountChangedEvent(aEvent, accessible, localName);
|
nsCOMPtr<nsIAccessibleTreeCache> treeAcc(do_QueryInterface(accessible));
|
||||||
|
NS_ASSERTION(treeAcc,
|
||||||
if (eventType.EqualsLiteral("TreeInvalidated"))
|
"Accessible for xul:tree doesn't implement nsIAccessibleTreeCache interface.");
|
||||||
return HandleTreeInvalidatedEvent(aEvent, accessible, localName);
|
|
||||||
|
if (treeAcc) {
|
||||||
|
if (eventType.EqualsLiteral("TreeViewChanged"))
|
||||||
|
return treeAcc->TreeViewChanged();
|
||||||
|
|
||||||
|
if (eventType.EqualsLiteral("TreeRowCountChanged"))
|
||||||
|
return HandleTreeRowCountChangedEvent(aEvent, treeAcc);
|
||||||
|
|
||||||
|
if (eventType.EqualsLiteral("TreeInvalidated"))
|
||||||
|
return HandleTreeInvalidatedEvent(aEvent, treeAcc);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (eventType.EqualsLiteral("RadioStateChange")) {
|
if (eventType.EqualsLiteral("RadioStateChange")) {
|
||||||
|
@ -1095,12 +1094,8 @@ NS_IMETHODIMP nsRootAccessible::FireDocLoadEvents(PRUint32 aEventType)
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsRootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent *aEvent,
|
nsRootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent *aEvent,
|
||||||
nsIAccessible *aAccessible,
|
nsIAccessibleTreeCache *aAccessible)
|
||||||
const nsAString& aTargetName)
|
|
||||||
{
|
{
|
||||||
if (!aTargetName.EqualsLiteral("tree"))
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
|
nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
|
||||||
if (!dataEvent)
|
if (!dataEvent)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -1121,20 +1116,13 @@ nsRootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent *aEvent,
|
||||||
indexVariant->GetAsInt32(&index);
|
indexVariant->GetAsInt32(&index);
|
||||||
countVariant->GetAsInt32(&count);
|
countVariant->GetAsInt32(&count);
|
||||||
|
|
||||||
nsCOMPtr<nsIAccessibleTreeCache> treeAccCache(do_QueryInterface(aAccessible));
|
return aAccessible->InvalidateCache(index, count);
|
||||||
NS_ENSURE_STATE(treeAccCache);
|
|
||||||
|
|
||||||
return treeAccCache->InvalidateCache(index, count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsRootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent *aEvent,
|
nsRootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent *aEvent,
|
||||||
nsIAccessible *aAccessible,
|
nsIAccessibleTreeCache *aAccessible)
|
||||||
const nsAString& aTargetName)
|
|
||||||
{
|
{
|
||||||
if (!aTargetName.EqualsLiteral("tree"))
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
|
nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
|
||||||
if (!dataEvent)
|
if (!dataEvent)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -1165,9 +1153,6 @@ nsRootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent *aEvent,
|
||||||
if (endColVariant)
|
if (endColVariant)
|
||||||
endColVariant->GetAsInt32(&endCol);
|
endColVariant->GetAsInt32(&endCol);
|
||||||
|
|
||||||
nsCOMPtr<nsIAccessibleTreeCache> treeAcc(do_QueryInterface(aAccessible));
|
return aAccessible->TreeViewInvalidated(startRow, endRow, startCol, endCol);
|
||||||
NS_ENSURE_STATE(treeAcc);
|
|
||||||
|
|
||||||
return treeAcc->TreeViewInvalidated(startRow, endRow, startCol, endCol);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,13 @@
|
||||||
#ifndef _nsRootAccessible_H_
|
#ifndef _nsRootAccessible_H_
|
||||||
#define _nsRootAccessible_H_
|
#define _nsRootAccessible_H_
|
||||||
|
|
||||||
|
#include "nsCaretAccessible.h"
|
||||||
#include "nsDocAccessibleWrap.h"
|
#include "nsDocAccessibleWrap.h"
|
||||||
#include "nsHashtable.h"
|
|
||||||
#include "nsIAccessibleDocument.h"
|
#include "nsIAccessibleDocument.h"
|
||||||
|
#include "nsIAccessibleTreeCache.h"
|
||||||
|
|
||||||
|
#include "nsHashtable.h"
|
||||||
#include "nsCaretAccessible.h"
|
#include "nsCaretAccessible.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIDOMFocusListener.h"
|
#include "nsIDOMFocusListener.h"
|
||||||
|
@ -124,15 +128,13 @@ class nsRootAccessible : public nsDocAccessibleWrap,
|
||||||
* Handles 'TreeRowCountChanged' event. Used in HandleEventWithTarget().
|
* Handles 'TreeRowCountChanged' event. Used in HandleEventWithTarget().
|
||||||
*/
|
*/
|
||||||
nsresult HandleTreeRowCountChangedEvent(nsIDOMEvent *aEvent,
|
nsresult HandleTreeRowCountChangedEvent(nsIDOMEvent *aEvent,
|
||||||
nsIAccessible *aAccessible,
|
nsIAccessibleTreeCache *aAccessible);
|
||||||
const nsAString& aTargetName);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles 'TreeInvalidated' event. Used in HandleEventWithTarget().
|
* Handles 'TreeInvalidated' event. Used in HandleEventWithTarget().
|
||||||
*/
|
*/
|
||||||
nsresult HandleTreeInvalidatedEvent(nsIDOMEvent *aEvent,
|
nsresult HandleTreeInvalidatedEvent(nsIDOMEvent *aEvent,
|
||||||
nsIAccessible *aAccessible,
|
nsIAccessibleTreeCache *aAccessible);
|
||||||
const nsAString& aTargetName);
|
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
PRUint32 GetChromeFlags();
|
PRUint32 GetChromeFlags();
|
||||||
|
|
|
@ -96,7 +96,9 @@ class nsAccessibleWrap : public nsAccessible
|
||||||
virtual already_AddRefed<nsIAccessible> GetUnignoredParent();
|
virtual already_AddRefed<nsIAccessible> GetUnignoredParent();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
virtual nsresult FirePlatformEvent(nsIAccessibleEvent *aEvent);
|
||||||
|
|
||||||
PRBool AncestorIsFlat() {
|
PRBool AncestorIsFlat() {
|
||||||
// we don't create a native object if we're child of a "flat" accessible; for example, on OS X buttons
|
// we don't create a native object if we're child of a "flat" accessible; for example, on OS X buttons
|
||||||
// shouldn't have any children, because that makes the OS confused.
|
// shouldn't have any children, because that makes the OS confused.
|
||||||
|
|
|
@ -169,8 +169,18 @@ nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
|
||||||
nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
|
nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return FirePlatformEvent(aEvent);
|
||||||
|
|
||||||
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsAccessibleWrap::FirePlatformEvent(nsIAccessibleEvent *aEvent)
|
||||||
|
{
|
||||||
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||||
|
|
||||||
PRUint32 eventType;
|
PRUint32 eventType;
|
||||||
rv = aEvent->GetEventType(&eventType);
|
nsresult rv = aEvent->GetEventType(&eventType);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// ignore everything but focus-changed and value-changed events for now.
|
// ignore everything but focus-changed and value-changed events for now.
|
||||||
|
|
|
@ -1690,6 +1690,12 @@ nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
|
||||||
nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
|
nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return FirePlatformEvent(aEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsAccessibleWrap::FirePlatformEvent(nsIAccessibleEvent *aEvent)
|
||||||
|
{
|
||||||
PRUint32 eventType = 0;
|
PRUint32 eventType = 0;
|
||||||
aEvent->GetEventType(&eventType);
|
aEvent->GetEventType(&eventType);
|
||||||
|
|
||||||
|
|
|
@ -313,6 +313,8 @@ class nsAccessibleWrap : public nsAccessible,
|
||||||
static IDispatch *NativeAccessible(nsIAccessible *aXPAccessible);
|
static IDispatch *NativeAccessible(nsIAccessible *aXPAccessible);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual nsresult FirePlatformEvent(nsIAccessibleEvent *aEvent);
|
||||||
|
|
||||||
// mEnumVARIANTPosition not the current accessible's position, but a "cursor" of
|
// mEnumVARIANTPosition not the current accessible's position, but a "cursor" of
|
||||||
// where we are in the current list of children, with respect to
|
// where we are in the current list of children, with respect to
|
||||||
// nsIEnumVariant::Reset(), Skip() and Next().
|
// nsIEnumVariant::Reset(), Skip() and Next().
|
||||||
|
|
|
@ -636,7 +636,7 @@ nsXULTreeAccessible::TreeViewInvalidated(PRInt32 aStartRow, PRInt32 aEndRow,
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
PRInt32 endRow = aEndRow, endCol = aEndCol;
|
PRInt32 endRow = aEndRow;
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
if (endRow == -1) {
|
if (endRow == -1) {
|
||||||
|
@ -652,6 +652,8 @@ nsXULTreeAccessible::TreeViewInvalidated(PRInt32 aStartRow, PRInt32 aEndRow,
|
||||||
NS_ENSURE_STATE(treeColumns);
|
NS_ENSURE_STATE(treeColumns);
|
||||||
|
|
||||||
#ifdef MOZ_ACCESSIBILITY_ATK
|
#ifdef MOZ_ACCESSIBILITY_ATK
|
||||||
|
PRInt32 endCol = aEndCol;
|
||||||
|
|
||||||
if (endCol == -1) {
|
if (endCol == -1) {
|
||||||
PRInt32 colCount = 0;
|
PRInt32 colCount = 0;
|
||||||
rv = treeColumns->GetCount(&colCount);
|
rv = treeColumns->GetCount(&colCount);
|
||||||
|
@ -705,6 +707,37 @@ nsXULTreeAccessible::TreeViewInvalidated(PRInt32 aStartRow, PRInt32 aEndRow,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void nsIAccessibleTreeCache::treeViewChanged();
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXULTreeAccessible::TreeViewChanged()
|
||||||
|
{
|
||||||
|
if (!mTree)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
// Fire only notification destroy/create events on accessible tree to lie to
|
||||||
|
// AT because it should be expensive to fire destroy events for each tree item
|
||||||
|
// in cache.
|
||||||
|
nsCOMPtr<nsIAccessibleEvent> eventDestroy =
|
||||||
|
new nsAccEvent(nsIAccessibleEvent::EVENT_DOM_DESTROY,
|
||||||
|
this, PR_FALSE);
|
||||||
|
NS_ENSURE_TRUE(eventDestroy, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
nsresult rv = FirePlatformEvent(eventDestroy);
|
||||||
|
|
||||||
|
ClearCache(*mAccessNodeCache);
|
||||||
|
|
||||||
|
mTree->GetView(getter_AddRefs(mTreeView));
|
||||||
|
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAccessibleEvent> eventCreate =
|
||||||
|
new nsAccEvent(nsIAccessibleEvent::EVENT_DOM_CREATE,
|
||||||
|
this, PR_FALSE);
|
||||||
|
NS_ENSURE_TRUE(eventCreate, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
return FirePlatformEvent(eventCreate);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult nsXULTreeAccessible::GetColumnCount(nsITreeBoxObject* aBoxObject, PRInt32* aCount)
|
nsresult nsXULTreeAccessible::GetColumnCount(nsITreeBoxObject* aBoxObject, PRInt32* aCount)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(aBoxObject, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(aBoxObject, NS_ERROR_FAILURE);
|
||||||
|
@ -714,7 +747,8 @@ nsresult nsXULTreeAccessible::GetColumnCount(nsITreeBoxObject* aBoxObject, PRInt
|
||||||
return treeColumns->GetCount(aCount);
|
return treeColumns->GetCount(aCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- nsXULTreeitemAccessible ----------
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// nsXULTreeitemAccessible
|
||||||
|
|
||||||
nsXULTreeitemAccessible::nsXULTreeitemAccessible(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell, PRInt32 aRow, nsITreeColumn* aColumn)
|
nsXULTreeitemAccessible::nsXULTreeitemAccessible(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell, PRInt32 aRow, nsITreeColumn* aColumn)
|
||||||
: nsLeafAccessible(aDOMNode, aShell)
|
: nsLeafAccessible(aDOMNode, aShell)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче