Bug 625652 - make sure accessible tree is correct when rendered text is changed, r=davidb, sr=roc, a=roc

This commit is contained in:
Alexander Surkov
2011-01-28 16:42:22 +08:00
parent abef44b088
commit 511e5584a7
10 changed files with 356 additions and 7 deletions

View File

@@ -56,6 +56,8 @@ NotificationController::NotificationController(nsDocAccessible* aDocument,
mObservingState(eNotObservingRefresh), mDocument(aDocument),
mPresShell(aPresShell), mTreeConstructedState(eTreeConstructionPending)
{
mTextHash.Init();
// Schedule initial accessible tree construction.
ScheduleProcessing();
}
@@ -113,6 +115,7 @@ NotificationController::Shutdown()
mDocument = nsnull;
mPresShell = nsnull;
mTextHash.Clear();
mContentInsertions.Clear();
mNotifications.Clear();
mEvents.Clear();
@@ -208,6 +211,11 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
if (!mDocument->IsBoundToParent())
return;
#ifdef DEBUG_NOTIFICATIONS
printf("\ninitial tree created, document: %p, document node: %p\n",
mDocument.get(), mDocument->GetDocumentNode());
#endif
mTreeConstructedState = eTreeConstructed;
mDocument->CacheChildrenInSubtree(mDocument);
@@ -235,6 +243,10 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
return;
}
// Process rendered text change notifications.
mTextHash.EnumerateEntries(TextEnumerator, mDocument);
mTextHash.Clear();
// Bind hanging child documents.
PRUint32 childDocCount = mHangingChildDocuments.Length();
for (PRUint32 idx = 0; idx < childDocCount; idx++) {
@@ -561,6 +573,89 @@ NotificationController::CreateTextChangeEventFor(AccMutationEvent* aEvent)
aEvent->mIsFromUserInput ? eFromUserInput : eNoUserInput);
}
PLDHashOperator
NotificationController::TextEnumerator(nsPtrHashKey<nsIContent>* aEntry,
void* aUserArg)
{
nsDocAccessible* document = static_cast<nsDocAccessible*>(aUserArg);
nsIContent* textNode = aEntry->GetKey();
nsAccessible* textAcc = document->GetAccessible(textNode);
// If the text node is not in tree or doesn't have frame then this case should
// have been handled already by content removal notifications.
nsINode* containerNode = textNode->GetNodeParent();
if (!containerNode) {
NS_ASSERTION(!textAcc,
"Text node was removed but accessible is kept alive!");
return PL_DHASH_NEXT;
}
nsIFrame* textFrame = textNode->GetPrimaryFrame();
if (!textFrame) {
NS_ASSERTION(!textAcc,
"Text node isn't rendered but accessible is kept alive!");
return PL_DHASH_NEXT;
}
nsIContent* containerElm = containerNode->IsElement() ?
containerNode->AsElement() : nsnull;
nsAutoString renderedText;
textFrame->GetRenderedText(&renderedText);
// Remove text accessible if rendered text is empty.
if (textAcc) {
if (renderedText.IsEmpty()) {
#ifdef DEBUG_NOTIFICATIONS
PRUint32 index = containerNode->IndexOf(textNode);
nsCAutoString tag;
nsCAutoString id;
if (containerElm) {
containerElm->Tag()->ToUTF8String(tag);
nsIAtom* atomid = containerElm->GetID();
if (atomid)
atomid->ToUTF8String(id);
}
printf("\npending text node removal: container: %s@id='%s', index in container: %d\n\n",
tag.get(), id.get(), index);
#endif
document->ContentRemoved(containerElm, textNode);
}
return PL_DHASH_NEXT;
}
// Append an accessible if rendered text is not empty.
if (!renderedText.IsEmpty()) {
#ifdef DEBUG_NOTIFICATIONS
PRUint32 index = containerNode->IndexOf(textNode);
nsCAutoString tag;
nsCAutoString id;
if (containerElm) {
containerElm->Tag()->ToUTF8String(tag);
nsIAtom* atomid = containerElm->GetID();
if (atomid)
atomid->ToUTF8String(id);
}
printf("\npending text node insertion: container: %s@id='%s', index in container: %d\n\n",
tag.get(), id.get(), index);
#endif
nsAccessible* container = document->GetAccessibleOrContainer(containerNode);
nsTArray<nsCOMPtr<nsIContent> > insertedContents;
insertedContents.AppendElement(textNode);
document->ProcessContentInserted(container, &insertedContents);
}
return PL_DHASH_NEXT;
}
////////////////////////////////////////////////////////////////////////////////
// NotificationController: content inserted notification
@@ -616,7 +711,7 @@ NotificationController::ContentInsertion::Process()
catomid->ToUTF8String(cid);
}
printf("\npending content insertion process: %s@id='%s', container: %s@id='%s', inserted content amount: %d\n\n",
printf("\npending content insertion: %s@id='%s', container: %s@id='%s', inserted content amount: %d\n\n",
tag.get(), id.get(), ctag.get(), cid.get(), mInsertedContent.Length());
#endif