From f573b9a821833610f0b247e64e548d75c38646e7 Mon Sep 17 00:00:00 2001 From: "aaronleventhal@moonset.net" Date: Sat, 2 Feb 2008 09:02:09 -0800 Subject: [PATCH] Bug 412931. Tabs not exposed unless 3 of them. Fix incorrect cache updates during flood of changes. r=surkov, a=schrep for b3 --- accessible/src/base/nsDocAccessible.cpp | 42 +++++++++++++++++++------ accessible/src/base/nsDocAccessible.h | 7 +++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/accessible/src/base/nsDocAccessible.cpp b/accessible/src/base/nsDocAccessible.cpp index cbc238fb9eb..365e384f727 100644 --- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -1507,14 +1507,22 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents() accessibleEvent->GetEventType(&eventType); if (eventType == nsIAccessibleEvent::EVENT_DOM_CREATE || eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) { + nsCOMPtr domNode; + accessibleEvent->GetDOMNode(getter_AddRefs(domNode)); nsCOMPtr containerAccessible; - if (accessible && eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) { - // For asynch show, delayed invalidatation of parent's children - accessible->GetParent(getter_AddRefs(containerAccessible)); - nsCOMPtr privateContainerAccessible = - do_QueryInterface(containerAccessible); - if (privateContainerAccessible) - privateContainerAccessible->InvalidateChildren(); + if (eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) { + if (accessible) { + // For asynch show, delayed invalidatation of parent's children + accessible->GetParent(getter_AddRefs(containerAccessible)); + nsCOMPtr privateContainerAccessible = + do_QueryInterface(containerAccessible); + if (privateContainerAccessible) + privateContainerAccessible->InvalidateChildren(); + } + // Some show events in the subtree may have been removed to + // avoid firing redundant events. But, we still need to make sure any + // accessibles parenting those shown nodes lose their child references. + InvalidateChildrenInSubtree(domNode); } // Also fire text changes if the node being created could affect the text in an nsIAccessibleText parent. @@ -1522,8 +1530,6 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents() // 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 domNode; - accessibleEvent->GetDOMNode(getter_AddRefs(domNode)); PRBool isFromUserInput; accessibleEvent->GetIsFromUserInput(&isFromUserInput); if (domNode && domNode != mDOMNode) { @@ -1622,6 +1628,24 @@ void nsDocAccessible::FlushEventsCallback(nsITimer *aTimer, void *aClosure) } } +void nsDocAccessible::InvalidateChildrenInSubtree(nsIDOMNode *aStartNode) +{ + nsCOMPtr accessNode; + GetCachedAccessNode(aStartNode, getter_AddRefs(accessNode)); + nsCOMPtr accessible(do_QueryInterface(accessNode)); + if (accessible) + accessible->InvalidateChildren(); + + // Invalidate accessible children in the DOM subtree + nsCOMPtr node = do_QueryInterface(aStartNode); + PRInt32 index, numChildren = node->GetChildCount(); + for (index = 0; index < numChildren; index ++) { + nsCOMPtr childNode = do_QueryInterface(node->GetChildAt(index)); + if (childNode) + InvalidateChildrenInSubtree(childNode); + } +} + void nsDocAccessible::RefreshNodes(nsIDOMNode *aStartNode) { if (mAccessNodeCache.Count() <= 1) { diff --git a/accessible/src/base/nsDocAccessible.h b/accessible/src/base/nsDocAccessible.h index 4151bb74297..671c5b4f4f7 100644 --- a/accessible/src/base/nsDocAccessible.h +++ b/accessible/src/base/nsDocAccessible.h @@ -143,6 +143,13 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap, virtual nsresult RemoveEventListeners(); void AddScrollListener(); void RemoveScrollListener(); + + /** + * For any accessibles in this subtree, invalidate their knowledge of + * their children. Only weak refrences are destroyed, not accessibles. + * @param aStartNode The root of the subrtee to invalidate accessible child refs in + */ + void InvalidateChildrenInSubtree(nsIDOMNode *aStartNode); void RefreshNodes(nsIDOMNode *aStartNode); static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);