Bug 1262420 - split updateTreeInternal for removals and insertions, part 2, r=yzen

This commit is contained in:
Alexander Surkov 2016-04-25 09:10:41 -04:00
parent e3f1739729
commit 446c271cb6
3 changed files with 49 additions and 73 deletions

View File

@ -160,6 +160,25 @@ DocAccessible::GetAccessibleEvenIfNotInMapOrContainer(nsINode* aNode) const
return acc ? acc : GetContainerAccessible(aNode);
}
inline void
DocAccessible::CreateSubtree(Accessible* aChild)
{
// If a focused node has been shown then it could mean its frame was recreated
// while the node stays focused and we need to fire focus event on
// the accessible we just created. If the queue contains a focus event for
// this node already then it will be suppressed by this one.
Accessible* focusedAcc = nullptr;
CacheChildrenInSubtree(aChild, &focusedAcc);
// XXX: do we really want to send focus to focused DOM node not taking into
// account active item?
if (focusedAcc) {
FocusMgr()->DispatchFocusEvent(this, focusedAcc);
SelectionMgr()->
SetControlSelectionListener(focusedAcc->GetNode()->AsElement());
}
}
} // namespace a11y
} // namespace mozilla

View File

@ -1762,7 +1762,6 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer,
aContainer);
#endif
uint32_t updateFlags = 0;
TreeMutation mt(aContainer);
do {
Accessible* parent = iter.Child()->Parent();
@ -1791,7 +1790,7 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer,
#endif
mt.AfterInsertion(iter.Child());
updateFlags |= UpdateTreeInternal(iter.Child(), true);
CreateSubtree(iter.Child());
continue;
}
@ -1805,7 +1804,7 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer,
aContainer);
#endif
FireEventsOnInsertion(aContainer, updateFlags);
FireEventsOnInsertion(aContainer);
}
void
@ -1828,25 +1827,18 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer, nsIContent* aNode)
mt.AfterInsertion(child);
mt.Done();
uint32_t flags = UpdateTreeInternal(child, true);
FireEventsOnInsertion(aContainer, flags);
CreateSubtree(child);
FireEventsOnInsertion(aContainer);
}
}
}
void
DocAccessible::FireEventsOnInsertion(Accessible* aContainer,
uint32_t aUpdateFlags)
DocAccessible::FireEventsOnInsertion(Accessible* aContainer)
{
// Content insertion did not cause an accessible tree change.
if (aUpdateFlags == eNoAccessible) {
return;
}
// Check to see if change occurred inside an alert, and fire an EVENT_ALERT
// if it did.
if (!(aUpdateFlags & eAlertAccessible) &&
(aContainer->IsAlert() || aContainer->IsInsideAlert())) {
if (aContainer->IsAlert() || aContainer->IsInsideAlert()) {
Accessible* ancestor = aContainer;
do {
if (ancestor->IsAlert()) {
@ -1897,45 +1889,6 @@ DocAccessible::UpdateTreeOnRemoval(Accessible* aContainer, nsIContent* aChildNod
mt.Done();
}
uint32_t
DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert)
{
uint32_t updateFlags = eAccessible;
// If a focused node has been shown then it could mean its frame was recreated
// while the node stays focused and we need to fire focus event on
// the accessible we just created. If the queue contains a focus event for
// this node already then it will be suppressed by this one.
Accessible* focusedAcc = nullptr;
if (aIsInsert) {
// Create accessible tree for shown accessible.
CacheChildrenInSubtree(aChild, &focusedAcc);
}
if (aIsInsert) {
roles::Role ariaRole = aChild->ARIARole();
if (ariaRole == roles::MENUPOPUP) {
// Fire EVENT_MENUPOPUP_START if ARIA menu appears.
FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
} else if (ariaRole == roles::ALERT) {
// Fire EVENT_ALERT if ARIA alert appears.
updateFlags = eAlertAccessible;
FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
}
}
// XXX: do we really want to send focus to focused DOM node not taking into
// account active item?
if (focusedAcc) {
FocusMgr()->DispatchFocusEvent(this, focusedAcc);
SelectionMgr()->SetControlSelectionListener(focusedAcc->GetNode()->AsElement());
}
return updateFlags;
}
bool
DocAccessible::RelocateARIAOwnedIfNeeded(nsIContent* aElement)
{
@ -2035,8 +1988,8 @@ DocAccessible::DoARIAOwnsRelocation(Accessible* aOwner)
insertIdx = child->IndexInParent() + 1;
arrayIdx++;
uint32_t flags = UpdateTreeInternal(child, true);
FireEventsOnInsertion(aOwner, flags);
CreateSubtree(child);
FireEventsOnInsertion(aOwner);
}
}
continue;
@ -2223,12 +2176,26 @@ DocAccessible::CacheChildrenInSubtree(Accessible* aRoot,
mt.Done();
}
// Fire document load complete on ARIA documents.
// XXX: we should delay an event if the ARIA document has aria-busy.
if (aRoot->HasARIARole() && !aRoot->IsDoc()) {
a11y::role role = aRoot->ARIARole();
if (role == roles::DIALOG || role == roles::DOCUMENT)
FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot);
// Fire events for ARIA elements.
if (!aRoot->HasARIARole()) {
return;
}
roles::Role role = aRoot->ARIARole();
if (role == roles::MENUPOPUP) {
FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aRoot);
return;
}
if (role == roles::ALERT) {
FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aRoot);
return;
}
// XXX: we should delay document load complete event if the ARIA document
// has aria-busy.
if (!aRoot->IsDoc() && (role == roles::DIALOG || role == roles::DOCUMENT)) {
FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot);
}
}

View File

@ -187,7 +187,7 @@ public:
*/
void FireDelayedEvent(AccEvent* aEvent);
void FireDelayedEvent(uint32_t aEventType, Accessible* aTarget);
void FireEventsOnInsertion(Accessible* aContainer, uint32_t aUpdateFlags);
void FireEventsOnInsertion(Accessible* aContainer);
/**
* Fire value change event on the given accessible if applicable.
@ -516,17 +516,6 @@ protected:
*/
void UpdateTreeOnRemoval(Accessible* aContainer, nsIContent* aChildNode);
/**
* Helper for UpdateTreeOn methods. Go down to DOM subtree and updates
* accessible tree. Return one of these flags.
*/
enum EUpdateTreeFlags {
eNoAccessible = 0,
eAccessible = 1,
eAlertAccessible = 2
};
uint32_t UpdateTreeInternal(Accessible* aChild, bool aIsInsert);
/**
* Validates all aria-owns connections and updates the tree accordingly.
*/
@ -555,6 +544,7 @@ protected:
*/
void CacheChildrenInSubtree(Accessible* aRoot,
Accessible** aFocusedAcc = nullptr);
void CreateSubtree(Accessible* aRoot);
/**
* Remove accessibles in subtree from node to accessible map.