Bug 391846. Fire correct text change events when a node is shown or hidden. r=surkov, sr=sicking, a=sicking
git-svn-id: svn://10.0.0.236/trunk@233243 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
f8270d4e58
commit
7e62128d84
@ -98,8 +98,8 @@ interface nsIAccessibilityService : nsIAccessibleRetrieval
|
||||
* EVENT_HIDE (destroy or hide)
|
||||
*/
|
||||
void invalidateSubtreeFor(in nsIPresShell aPresShell,
|
||||
in nsIContent aChangedContent,
|
||||
in PRUint32 aEvent);
|
||||
in nsIContent aChangedContent,
|
||||
in PRUint32 aEvent);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -553,6 +553,11 @@ interface nsIAccessibleTextChangeEvent : nsIAccessibleEvent
|
||||
* Returns true if text was inserted, otherwise false.
|
||||
*/
|
||||
boolean isInserted();
|
||||
|
||||
/**
|
||||
* The inserted or removed text
|
||||
*/
|
||||
readonly attribute DOMString modifiedText;
|
||||
};
|
||||
|
||||
[scriptable, uuid(b9076dce-4cd3-4e3d-a7f6-7f33a7f40c31)]
|
||||
|
||||
@ -1804,11 +1804,14 @@ NS_IMETHODIMP nsAccessibilityService::InvalidateSubtreeFor(nsIPresShell *aShell,
|
||||
{
|
||||
NS_ASSERTION(aEvent == nsIAccessibleEvent::EVENT_ASYNCH_SIGNIFICANT_CHANGE ||
|
||||
aEvent == nsIAccessibleEvent::EVENT_ASYNCH_SHOW ||
|
||||
aEvent == nsIAccessibleEvent::EVENT_ASYNCH_HIDE,
|
||||
aEvent == nsIAccessibleEvent::EVENT_ASYNCH_HIDE ||
|
||||
aEvent == nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE ||
|
||||
aEvent == nsIAccessibleEvent::EVENT_DOM_CREATE ||
|
||||
aEvent == nsIAccessibleEvent::EVENT_DOM_DESTROY,
|
||||
"Incorrect aEvent passed in");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aShell);
|
||||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aShell));
|
||||
NS_ASSERTION(aShell, "No pres shell in call to InvalidateSubtreeFor");
|
||||
nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
|
||||
nsAccessNode::GetDocAccessibleFor(weakShell);
|
||||
nsCOMPtr<nsPIAccessibleDocument> privateAccessibleDoc =
|
||||
|
||||
@ -394,11 +394,16 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsAccTextChangeEvent, nsAccEvent,
|
||||
|
||||
nsAccTextChangeEvent::
|
||||
nsAccTextChangeEvent(nsIAccessible *aAccessible,
|
||||
PRInt32 aStart, PRUint32 aLength, PRBool aIsInserted):
|
||||
PRInt32 aStart, PRUint32 aLength, PRBool aIsInserted, PRBool aIsAsynch):
|
||||
nsAccEvent(aIsInserted ? nsIAccessibleEvent::EVENT_TEXT_INSERTED : nsIAccessibleEvent::EVENT_TEXT_REMOVED,
|
||||
aAccessible, nsnull),
|
||||
aAccessible, nsnull, aIsAsynch),
|
||||
mStart(aStart), mLength(aLength), mIsInserted(aIsInserted)
|
||||
{
|
||||
nsCOMPtr<nsIAccessibleText> textAccessible = do_QueryInterface(aAccessible);
|
||||
NS_ASSERTION(textAccessible, "Should not be firing test change event for non-text accessible!!!");
|
||||
if (textAccessible) {
|
||||
textAccessible->GetText(aStart, aStart + aLength, mModifiedText);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -422,6 +427,13 @@ nsAccTextChangeEvent::IsInserted(PRBool *aIsInserted)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAccTextChangeEvent::GetModifiedText(nsAString& aModifiedText)
|
||||
{
|
||||
aModifiedText = mModifiedText;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsAccCaretMoveEvent
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsAccCaretMoveEvent, nsAccEvent,
|
||||
nsIAccessibleCaretMoveEvent)
|
||||
|
||||
@ -46,6 +46,8 @@
|
||||
#include "nsIAccessible.h"
|
||||
#include "nsIAccessibleDocument.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIPresShell;
|
||||
|
||||
class nsAccEvent: public nsIAccessibleEvent
|
||||
@ -128,8 +130,8 @@ class nsAccTextChangeEvent: public nsAccEvent,
|
||||
public nsIAccessibleTextChangeEvent
|
||||
{
|
||||
public:
|
||||
nsAccTextChangeEvent(nsIAccessible *aAccessible,
|
||||
PRInt32 aStart, PRUint32 aLength, PRBool aIsInserted);
|
||||
nsAccTextChangeEvent(nsIAccessible *aAccessible, PRInt32 aStart, PRUint32 aLength,
|
||||
PRBool aIsInserted, PRBool aIsAsynch = PR_FALSE);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_NSIACCESSIBLEEVENT(nsAccEvent::)
|
||||
@ -139,6 +141,7 @@ private:
|
||||
PRInt32 mStart;
|
||||
PRUint32 mLength;
|
||||
PRBool mIsInserted;
|
||||
nsString mModifiedText;
|
||||
};
|
||||
|
||||
class nsAccCaretMoveEvent: public nsAccEvent,
|
||||
|
||||
@ -1149,9 +1149,6 @@ void nsDocAccessible::ContentAppended(nsIDocument *aDocument,
|
||||
PRUint32 childCount = aContainer->GetChildCount();
|
||||
for (PRUint32 index = aNewIndexInContainer; index < childCount; index ++) {
|
||||
nsCOMPtr<nsIContent> child(aContainer->GetChildAt(index));
|
||||
|
||||
FireTextChangedEventOnDOMNodeInserted(child, aContainer, index);
|
||||
|
||||
// InvalidateCacheSubtree will not fire the EVENT_SHOW for the new node
|
||||
// unless an accessible can be created for the passed in node, which it
|
||||
// can't do unless the node is visible. The right thing happens there so
|
||||
@ -1184,8 +1181,6 @@ void
|
||||
nsDocAccessible::ContentInserted(nsIDocument *aDocument, nsIContent* aContainer,
|
||||
nsIContent* aChild, PRInt32 aIndexInContainer)
|
||||
{
|
||||
FireTextChangedEventOnDOMNodeInserted(aChild, aContainer, aIndexInContainer);
|
||||
|
||||
// InvalidateCacheSubtree will not fire the EVENT_SHOW for the new node
|
||||
// unless an accessible can be created for the passed in node, which it
|
||||
// can't do unless the node is visible. The right thing happens there so
|
||||
@ -1197,10 +1192,11 @@ void
|
||||
nsDocAccessible::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
|
||||
nsIContent* aChild, PRInt32 aIndexInContainer)
|
||||
{
|
||||
FireTextChangedEventOnDOMNodeRemoved(aChild, aContainer, aIndexInContainer);
|
||||
|
||||
// Invalidate the subtree of the removed element.
|
||||
InvalidateCacheSubtree(aChild, nsIAccessibleEvent::EVENT_DOM_DESTROY);
|
||||
// InvalidateCacheSubtree(aChild, nsIAccessibleEvent::EVENT_DOM_DESTROY);
|
||||
// This is no longer needed, we get our notifications directly from content
|
||||
// *before* the frame for the content is destroyed, or any other side effects occur.
|
||||
// That allows us to correctly calculate the TEXT_REMOVED event if there is one.
|
||||
}
|
||||
|
||||
void
|
||||
@ -1256,122 +1252,82 @@ nsDocAccessible::FireTextChangedEventOnDOMCharacterDataModified(nsIContent *aCon
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDocAccessible::FireTextChangedEventOnDOMNodeInserted(nsIContent *aChild,
|
||||
nsIContent *aContainer,
|
||||
PRInt32 aIndexInContainer)
|
||||
already_AddRefed<nsIAccessibleTextChangeEvent>
|
||||
nsDocAccessible::CreateTextChangeEventForNode(nsIAccessible *aContainerAccessible,
|
||||
nsIDOMNode *aChangeNode,
|
||||
nsIAccessible *aAccessibleForChangeNode,
|
||||
PRBool aIsInserting,
|
||||
PRBool aIsAsynch)
|
||||
{
|
||||
if (!mIsContentLoaded || !mDocument) {
|
||||
return;
|
||||
nsRefPtr<nsHyperTextAccessible> textAccessible;
|
||||
aContainerAccessible->QueryInterface(NS_GET_IID(nsHyperTextAccessible),
|
||||
getter_AddRefs(textAccessible));
|
||||
if (!textAccessible) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aChild));
|
||||
if (!node)
|
||||
return;
|
||||
PRInt32 offset;
|
||||
PRInt32 length = 0;
|
||||
nsCOMPtr<nsIAccessible> changeAccessible;
|
||||
nsresult rv = textAccessible->DOMPointToHypertextOffset(aChangeNode, -1, &offset,
|
||||
getter_AddRefs(changeAccessible));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
nsresult rv = GetAccessibleInParentChain(node, getter_AddRefs(accessible));
|
||||
if (NS_FAILED(rv) || !accessible)
|
||||
return;
|
||||
|
||||
nsRefPtr<nsHyperTextAccessible> textAccessible;
|
||||
rv = accessible->QueryInterface(NS_GET_IID(nsHyperTextAccessible),
|
||||
getter_AddRefs(textAccessible));
|
||||
if (NS_FAILED(rv) || !textAccessible)
|
||||
return;
|
||||
|
||||
PRUint32 length = 1;
|
||||
if (aChild && aChild->IsNodeOfType(nsINode::eTEXT)) {
|
||||
length = aChild->TextLength();
|
||||
if (!length)
|
||||
return;
|
||||
} else {
|
||||
// Don't fire event for the first html:br in an editor.
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
textAccessible->GetAssociatedEditor(getter_AddRefs(editor));
|
||||
if (editor) {
|
||||
PRBool isEmpty = PR_FALSE;
|
||||
editor->GetDocumentIsEmpty(&isEmpty);
|
||||
if (isEmpty)
|
||||
return;
|
||||
if (!aAccessibleForChangeNode) {
|
||||
// A span-level object or something else without an accessible is being removed, where
|
||||
// it has no accessible but it has descendant content which is aggregated as text
|
||||
// into the parent hypertext.
|
||||
// In this case, accessibleToBeRemoved may just be the first
|
||||
// accessible that is removed, which affects the text in the hypertext container
|
||||
if (!changeAccessible) {
|
||||
return nsnull; // No descendant content that represents any text in the hypertext parent
|
||||
}
|
||||
nsCOMPtr<nsIAccessible> child = changeAccessible;
|
||||
while (PR_TRUE) {
|
||||
nsCOMPtr<nsIAccessNode> childAccessNode =
|
||||
do_QueryInterface(changeAccessible);
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
childAccessNode->GetDOMNode(getter_AddRefs(childNode));
|
||||
if (!nsAccUtils::IsAncestorOf(aChangeNode, childNode)) {
|
||||
break; // We only want accessibles with DOM nodes as children of this node
|
||||
}
|
||||
length += TextLength(child);
|
||||
child->GetNextSibling(getter_AddRefs(changeAccessible));
|
||||
if (!changeAccessible) {
|
||||
break;
|
||||
}
|
||||
child.swap(changeAccessible);
|
||||
}
|
||||
}
|
||||
else {
|
||||
NS_ASSERTION(changeAccessible == aAccessibleForChangeNode,
|
||||
"Hypertext is reporting a different accessible for this node");
|
||||
length = TextLength(aAccessibleForChangeNode);
|
||||
if (Role(aAccessibleForChangeNode) == nsIAccessibleRole::ROLE_WHITESPACE) { // newline
|
||||
// Don't fire event for the first html:br in an editor.
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
textAccessible->GetAssociatedEditor(getter_AddRefs(editor));
|
||||
if (editor) {
|
||||
PRBool isEmpty = PR_FALSE;
|
||||
editor->GetDocumentIsEmpty(&isEmpty);
|
||||
if (isEmpty) {
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parentNode(do_QueryInterface(aContainer));
|
||||
if (!parentNode)
|
||||
return;
|
||||
|
||||
PRInt32 offset = 0;
|
||||
rv = textAccessible->DOMPointToHypertextOffset(parentNode, aIndexInContainer, &offset);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIAccessibleTextChangeEvent> event =
|
||||
new nsAccTextChangeEvent(accessible, offset, length, PR_TRUE);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
textAccessible->FireAccessibleEvent(event);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocAccessible::FireTextChangedEventOnDOMNodeRemoved(nsIContent *aChild,
|
||||
nsIContent *aContainer,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
if (!mIsContentLoaded || !mDocument) {
|
||||
return;
|
||||
if (length <= 0) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aChild));
|
||||
if (!node)
|
||||
return;
|
||||
nsIAccessibleTextChangeEvent *event =
|
||||
new nsAccTextChangeEvent(aContainerAccessible, offset, length, aIsInserting, aIsAsynch);
|
||||
NS_IF_ADDREF(event);
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
nsresult rv = GetAccessibleInParentChain(node, getter_AddRefs(accessible));
|
||||
if (NS_FAILED(rv) || !accessible)
|
||||
return;
|
||||
|
||||
nsRefPtr<nsHyperTextAccessible> textAccessible;
|
||||
rv = accessible->QueryInterface(NS_GET_IID(nsHyperTextAccessible),
|
||||
getter_AddRefs(textAccessible));
|
||||
if (NS_FAILED(rv) || !textAccessible)
|
||||
return;
|
||||
|
||||
PRUint32 length = 1;
|
||||
if (aChild && aChild->IsNodeOfType(nsINode::eTEXT)) {
|
||||
length = aChild->TextLength();
|
||||
if (!length)
|
||||
return;
|
||||
} else {
|
||||
// Don't fire event for the last html:br in an editor.
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
textAccessible->GetAssociatedEditor(getter_AddRefs(editor));
|
||||
if (editor) {
|
||||
PRBool isEmpty = PR_FALSE;
|
||||
editor->GetDocumentIsEmpty(&isEmpty);
|
||||
if (isEmpty)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parentNode(do_QueryInterface(aContainer));
|
||||
if (!parentNode)
|
||||
return;
|
||||
|
||||
PRInt32 offset = 0;
|
||||
rv = textAccessible->DOMPointToHypertextOffset(parentNode, aIndexInContainer, &offset);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIAccessibleTextChangeEvent> event =
|
||||
new nsAccTextChangeEvent(accessible, offset, length, PR_FALSE);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
textAccessible->FireAccessibleEvent(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsDocAccessible::FireDelayedToolkitEvent(PRUint32 aEvent,
|
||||
nsIDOMNode *aDOMNode,
|
||||
void *aData,
|
||||
@ -1492,9 +1448,38 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
accessibleEvent->GetAccessible(getter_AddRefs(accessible));
|
||||
|
||||
PRUint32 eventType;
|
||||
accessibleEvent->GetEventType(&eventType);
|
||||
if (eventType == nsIAccessibleEvent::EVENT_DOM_CREATE ||
|
||||
eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) {
|
||||
// Also fire text changes if the node being created could affect the text in an nsIAccessibleText parent.
|
||||
// When a node is being made visible or is inserted, the text in an ancestor hyper text will gain characters
|
||||
// At this point we now have the frame and accessible for this node if there is one. That is why we
|
||||
// wait to fire this here, instead of in InvalidateCacheSubtree(), where we wouldn't be able to calculate
|
||||
// the offset, length and text for the text change.
|
||||
nsCOMPtr<nsIDOMNode> domNode;
|
||||
accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
|
||||
if (domNode && domNode != mDOMNode) {
|
||||
nsCOMPtr<nsIAccessible> containerAccessible;
|
||||
GetAccessibleInParentChain(domNode, getter_AddRefs(containerAccessible));
|
||||
nsCOMPtr<nsIAccessibleTextChangeEvent> textChangeEvent =
|
||||
CreateTextChangeEventForNode(containerAccessible, domNode, accessible, PR_TRUE, PR_TRUE);
|
||||
if (textChangeEvent) {
|
||||
PRBool isFromUserInput;
|
||||
accessibleEvent->GetIsFromUserInput(&isFromUserInput);
|
||||
nsCOMPtr<nsIDOMNode> hyperTextNode;
|
||||
textChangeEvent->GetDOMNode(getter_AddRefs(hyperTextNode));
|
||||
nsAccEvent::PrepareForEvent(hyperTextNode, isFromUserInput);
|
||||
// XXX Queue them up and merge the text change events
|
||||
// XXX We need a way to ignore SplitNode and JoinNode() when they
|
||||
// do not affect the text within the hypertext
|
||||
FireAccessibleEvent(textChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (accessible) {
|
||||
PRUint32 eventType;
|
||||
accessibleEvent->GetEventType(&eventType);
|
||||
if (eventType == nsIAccessibleEvent::EVENT_INTERNAL_LOAD) {
|
||||
nsCOMPtr<nsPIAccessibleDocument> docAccessible =
|
||||
do_QueryInterface(accessible);
|
||||
@ -1534,6 +1519,14 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
|
||||
// Post event processing
|
||||
if (eventType == nsIAccessibleEvent::EVENT_ASYNCH_HIDE ||
|
||||
eventType == nsIAccessibleEvent::EVENT_DOM_DESTROY) {
|
||||
// Invalidate children
|
||||
nsCOMPtr<nsIAccessible> containerAccessible;
|
||||
accessible->GetParent(getter_AddRefs(containerAccessible));
|
||||
nsCOMPtr<nsPIAccessible> privateContainerAccessible =
|
||||
do_QueryInterface(containerAccessible);
|
||||
if (privateContainerAccessible) {
|
||||
privateContainerAccessible->InvalidateChildren();
|
||||
}
|
||||
// Shutdown nsIAccessNode's or nsIAccessibles for any DOM nodes in this subtree
|
||||
nsCOMPtr<nsIDOMNode> hidingNode;
|
||||
accessibleEvent->GetDOMNode(getter_AddRefs(hidingNode));
|
||||
@ -1702,6 +1695,12 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIAccessible> containerAccessible;
|
||||
GetAccessibleInParentChain(childNode, getter_AddRefs(containerAccessible));
|
||||
if (!containerAccessible) {
|
||||
containerAccessible = this;
|
||||
}
|
||||
|
||||
if (!isShowing) {
|
||||
// Fire EVENT_ASYNCH_HIDE or EVENT_DOM_DESTROY if previous accessible existed for node being hidden.
|
||||
// Fire this before the accessible goes away.
|
||||
@ -1713,6 +1712,19 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
|
||||
NS_ENSURE_TRUE(removalEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
FireDelayedAccessibleEvent(removalEvent, eCoalesceFromSameSubtree, isAsynch);
|
||||
}
|
||||
if (childNode != mDOMNode) { // Fire text change unless the node being removed is for this doc
|
||||
// When a node is hidden or removed, the text in an ancestor hyper text will lose characters
|
||||
// At this point we still have the frame and accessible for this node if there was one
|
||||
// XXX Collate events when a range is deleted
|
||||
// XXX We need a way to ignore SplitNode and JoinNode() when they
|
||||
// do not affect the text within the hypertext
|
||||
nsCOMPtr<nsIAccessibleTextChangeEvent> textChangeEvent =
|
||||
CreateTextChangeEventForNode(containerAccessible, childNode, childAccessible,
|
||||
PR_FALSE, isAsynch);
|
||||
if (textChangeEvent) {
|
||||
FireAccessibleEvent(textChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We need to get an accessible for the mutation event's container node
|
||||
@ -1722,18 +1734,12 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
|
||||
// We're guaranteed success, because we will eventually end up at the doc accessible,
|
||||
// and there is always one of those.
|
||||
|
||||
nsCOMPtr<nsIAccessible> containerAccessible;
|
||||
GetAccessibleInParentChain(childNode, getter_AddRefs(containerAccessible));
|
||||
if (!containerAccessible) {
|
||||
containerAccessible = this;
|
||||
}
|
||||
nsCOMPtr<nsPIAccessible> privateContainerAccessible =
|
||||
do_QueryInterface(containerAccessible);
|
||||
if (privateContainerAccessible) {
|
||||
privateContainerAccessible->InvalidateChildren();
|
||||
}
|
||||
|
||||
if (aChild && !isHiding) {
|
||||
nsCOMPtr<nsPIAccessible> privateContainerAccessible =
|
||||
do_QueryInterface(containerAccessible);
|
||||
if (privateContainerAccessible) {
|
||||
privateContainerAccessible->InvalidateChildren();
|
||||
}
|
||||
// Fire EVENT_SHOW, EVENT_MENUPOPUP_START for newly visible content.
|
||||
// Fire after a short timer, because we want to make sure the view has been
|
||||
// updated to make this accessible content visible. If we don't wait,
|
||||
|
||||
@ -107,7 +107,7 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap,
|
||||
/**
|
||||
* Non-virtual method to fire a delayed event after a 0 length timeout
|
||||
*
|
||||
* @param aEvent - the nsIAccessibleEvent event ype
|
||||
* @param aEvent - the nsIAccessibleEvent event type
|
||||
* @param aDOMNode - DOM node the accesible event should be fired for
|
||||
* @param aData - any additional data for the event
|
||||
* @param aAllowDupes - eAllowDupes: more than one event of the same type is allowed.
|
||||
@ -161,21 +161,20 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap,
|
||||
*/
|
||||
void FireTextChangedEventOnDOMCharacterDataModified(nsIContent *aContent,
|
||||
CharacterDataChangeInfo* aInfo);
|
||||
/**
|
||||
* Fire text changed event for the inserted element if it is inside a text
|
||||
* accessible.
|
||||
*/
|
||||
void FireTextChangedEventOnDOMNodeInserted(nsIContent *aChild,
|
||||
nsIContent *aContainer,
|
||||
PRInt32 aIndexInContainer);
|
||||
|
||||
/**
|
||||
* Fire text changed event for the removed element if it is inside a text
|
||||
* accessible.
|
||||
* Create a text change event for a changed node
|
||||
* @param aContainerAccessible, the first accessible in the container
|
||||
* @param aChangeNode, the node that is being inserted or removed, or shown/hidden
|
||||
* @param aAccessibleForChangeNode, the accessible for that node, or nsnull if none exists
|
||||
* @param aIsInserting, is aChangeNode being created or shown (vs. removed or hidden)
|
||||
*/
|
||||
void FireTextChangedEventOnDOMNodeRemoved(nsIContent *aChild,
|
||||
nsIContent *aContainer,
|
||||
PRInt32 aIndexInContainer);
|
||||
already_AddRefed<nsIAccessibleTextChangeEvent>
|
||||
nsDocAccessible::CreateTextChangeEventForNode(nsIAccessible *aContainerAccessible,
|
||||
nsIDOMNode *aChangeNode,
|
||||
nsIAccessible *aAccessibleForNode,
|
||||
PRBool aIsInserting,
|
||||
PRBool aIsAsynch);
|
||||
|
||||
nsAccessNodeHashtable mAccessNodeCache;
|
||||
void *mWnd;
|
||||
|
||||
@ -62,9 +62,9 @@ NS_IMETHODIMP nsHTMLTextAccessible::GetName(nsAString& aName)
|
||||
NS_IMETHODIMP nsHTMLTextAccessible::GetRole(PRUint32 *aRole)
|
||||
{
|
||||
nsIFrame *frame = GetFrame();
|
||||
NS_ENSURE_TRUE(frame, NS_ERROR_NULL_POINTER);
|
||||
|
||||
if (frame->IsGeneratedContentFrame()) {
|
||||
// Don't return on null frame -- we still return a role
|
||||
// after accessible is shutdown/DEFUNCT
|
||||
if (frame && frame->IsGeneratedContentFrame()) {
|
||||
*aRole = nsIAccessibleRole::ROLE_STATICTEXT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -526,7 +526,6 @@ nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRI
|
||||
NS_ENSURE_ARG_POINTER(aHyperTextOffset);
|
||||
*aHyperTextOffset = 0;
|
||||
NS_ENSURE_ARG_POINTER(aNode);
|
||||
NS_ENSURE_TRUE(aNodeOffset >= 0, NS_ERROR_INVALID_ARG);
|
||||
if (aFinalAccessible) {
|
||||
*aFinalAccessible = nsnull;
|
||||
}
|
||||
@ -536,7 +535,10 @@ nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRI
|
||||
|
||||
unsigned short nodeType;
|
||||
aNode->GetNodeType(&nodeType);
|
||||
if (nodeType == nsIDOMNode::TEXT_NODE) {
|
||||
if (aNodeOffset == -1) {
|
||||
findNode = aNode;
|
||||
}
|
||||
else if (nodeType == nsIDOMNode::TEXT_NODE) {
|
||||
// For text nodes, aNodeOffset comes in as a character offset
|
||||
// Text offset will be added at the end, if we find the offset in this hypertext
|
||||
// We want the "skipped" offset into the text (rendered text without the extra whitespace)
|
||||
@ -618,6 +620,7 @@ nsresult nsHyperTextAccessible::DOMPointToHypertextOffset(nsIDOMNode* aNode, PRI
|
||||
NS_ADDREF(*aFinalAccessible = childAccessible);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -101,6 +101,9 @@ public:
|
||||
*
|
||||
* @param aNode - the node to look for
|
||||
* @param aNodeOffset - the offset to look for
|
||||
* if -1 just look directly for the node
|
||||
* if >=0 and aNode is text, this represents a char offset
|
||||
* if >=0 and aNode is not text, this represents a child node offset
|
||||
* @param aResultOffset - the character offset into the current
|
||||
* nsHyperTextAccessible
|
||||
* @param aFinalAccessible [optional] - returns the accessible child which
|
||||
|
||||
@ -89,28 +89,24 @@ nsHyperTextAccessibleWrap::GetModifiedText(PRBool aGetInsertedText,
|
||||
|
||||
if (!gTextEvent)
|
||||
return NS_OK;
|
||||
|
||||
PRBool isInserted;
|
||||
gTextEvent->IsInserted(&isInserted);
|
||||
if (aGetInsertedText != isInserted)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIAccessible> targetAcc;
|
||||
gTextEvent->GetAccessible(getter_AddRefs(targetAcc));
|
||||
if (targetAcc != this)
|
||||
return NS_OK;
|
||||
|
||||
PRBool isInserted;
|
||||
gTextEvent->IsInserted(&isInserted);
|
||||
|
||||
if (aGetInsertedText != isInserted)
|
||||
return NS_OK;
|
||||
|
||||
nsAutoString text;
|
||||
PRInt32 offset;
|
||||
PRUint32 length;
|
||||
|
||||
gTextEvent->GetStart(&offset);
|
||||
gTextEvent->GetLength(&length);
|
||||
GetText(offset, offset + length, aText);
|
||||
*aStartOffset = offset;
|
||||
*aEndOffset = offset + length;
|
||||
|
||||
return NS_OK;
|
||||
return gTextEvent->GetModifiedText(aText);
|
||||
}
|
||||
|
||||
|
||||
@ -82,6 +82,7 @@ REQUIRES = xpcom \
|
||||
util \
|
||||
appshell \
|
||||
shistory \
|
||||
accessibility \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
||||
@ -125,6 +125,11 @@
|
||||
#include "nsIXULDocument.h"
|
||||
#endif /* MOZ_XUL */
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "nsIAccessibilityService.h"
|
||||
#include "nsIAccessibleEvent.h"
|
||||
#endif /* ACCESSIBILITY */
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsCCUncollectableMarker.h"
|
||||
#include "nsCycleCollector.h"
|
||||
@ -2694,6 +2699,22 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
|
||||
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
|
||||
"Incorrect aDocument");
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
// A11y needs to be notified of content removals first, so accessibility
|
||||
// events can be fired before any changes occur
|
||||
if (aNotify && aDocument) {
|
||||
nsIPresShell *presShell = aDocument->GetPrimaryShell();
|
||||
if (presShell && presShell->IsAccessibilityActive()) {
|
||||
nsCOMPtr<nsIAccessibilityService> accService =
|
||||
do_GetService("@mozilla.org/accessibilityService;1");
|
||||
if (accService) {
|
||||
accService->InvalidateSubtreeFor(presShell, aKid,
|
||||
nsIAccessibleEvent::EVENT_DOM_DESTROY);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsMutationGuard::DidMutate();
|
||||
|
||||
nsINode* container = NODE_FROM(aParent, aDocument);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user