rpms/xulrunner/devel xulrunner-a11y.patch, NONE, 1.1 .cvsignore, 1.40, 1.41 sources, 1.41, 1.42 xulrunner.spec, 1.96, 1.97

Christopher Aillon (caillon) fedora-extras-commits at redhat.com
Mon Mar 17 03:28:34 UTC 2008


Author: caillon

Update of /cvs/extras/rpms/xulrunner/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv22397

Modified Files:
	.cvsignore sources xulrunner.spec 
Added Files:
	xulrunner-a11y.patch 
Log Message:
* Sat Mar 16 2008 Christopher Aillon <caillon at redhat.com> 1.9-0.43
- Update to latest trunk (2008-03-16)
- Add patch to negate a11y slowdown on some pages (#431162)


xulrunner-a11y.patch:

--- NEW FILE xulrunner-a11y.patch ---
a11y perf patch from https://bugzilla.mozilla.org/show_bug.cgi?id=418845


Index: accessible/src/base/nsAccessibilityUtils.cpp
===================================================================
RCS file: /cvsroot/mozilla/accessible/accessible/src/base/nsAccessibilityUtils.cpp,v
retrieving revision 1.27
diff -u -p -8 -r1.27 nsAccessibilityUtils.cpp
--- accessible/src/base/nsAccessibilityUtils.cpp	20 Feb 2008 07:50:45 -0000	1.27
+++ accessible/src/base/nsAccessibilityUtils.cpp	13 Mar 2008 02:36:00 -0000
@@ -314,31 +314,45 @@ nsAccUtils::FireAccEvent(PRUint32 aEvent
 
   return pAccessible->FireAccessibleEvent(event);
 }
 
 PRBool
 nsAccUtils::IsAncestorOf(nsIDOMNode *aPossibleAncestorNode,
                          nsIDOMNode *aPossibleDescendantNode)
 {
-  NS_ENSURE_TRUE(aPossibleAncestorNode, PR_FALSE);
-  NS_ENSURE_TRUE(aPossibleDescendantNode, PR_FALSE);
+  NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, PR_FALSE);
 
   nsCOMPtr<nsIDOMNode> loopNode = aPossibleDescendantNode;
   nsCOMPtr<nsIDOMNode> parentNode;
   while (NS_SUCCEEDED(loopNode->GetParentNode(getter_AddRefs(parentNode))) &&
          parentNode) {
     if (parentNode == aPossibleAncestorNode) {
       return PR_TRUE;
     }
     loopNode.swap(parentNode);
   }
   return PR_FALSE;
 }
 
+PRBool
+nsAccUtils::AreSiblings(nsIDOMNode *aDOMNode1,
+                       nsIDOMNode *aDOMNode2)
+{
+  NS_ENSURE_TRUE(aDOMNode1 && aDOMNode2, PR_FALSE);
+
+  nsCOMPtr<nsIDOMNode> parentNode1, parentNode2;
+  if (NS_SUCCEEDED(aDOMNode1->GetParentNode(getter_AddRefs(parentNode1))) &&
+      NS_SUCCEEDED(aDOMNode2->GetParentNode(getter_AddRefs(parentNode2))) &&
+      parentNode1 == parentNode2) {
+    return PR_TRUE;
+  }
+  return PR_FALSE;
+}
+
 already_AddRefed<nsIAccessible>
 nsAccUtils::GetAncestorWithRole(nsIAccessible *aDescendant, PRUint32 aRole)
 {
   nsCOMPtr<nsIAccessible> parentAccessible = aDescendant, testRoleAccessible;
   while (NS_SUCCEEDED(parentAccessible->GetParent(getter_AddRefs(testRoleAccessible))) &&
          testRoleAccessible) {
     PRUint32 testRole;
     testRoleAccessible->GetFinalRole(&testRole);
Index: accessible/src/base/nsAccessibilityUtils.h
===================================================================
RCS file: /cvsroot/mozilla/accessible/accessible/src/base/nsAccessibilityUtils.h,v
retrieving revision 1.21
diff -u -p -8 -r1.21 nsAccessibilityUtils.h
--- accessible/src/base/nsAccessibilityUtils.h	12 Feb 2008 07:24:05 -0000	1.21
+++ accessible/src/base/nsAccessibilityUtils.h	13 Mar 2008 02:36:00 -0000
@@ -144,16 +144,23 @@ public:
    * @param aPossibleAncestorNode -- node to test for ancestor-ness of aPossibleDescendantNode
    * @param aPossibleDescendantNode -- node to test for descendant-ness of aPossibleAncestorNode
    * @return PR_TRUE if aPossibleAncestorNode is an ancestor of aPossibleDescendantNode
    */
    static PRBool IsAncestorOf(nsIDOMNode *aPossibleAncestorNode,
                               nsIDOMNode *aPossibleDescendantNode);
 
   /**
+   * Are the first node and the second siblings?
+   * @return PR_TRUE if aDOMNode1 and aDOMNode2 have same parent
+   */
+   static PRBool AreSiblings(nsIDOMNode *aDOMNode1,
+                            nsIDOMNode *aDOMNode2);
+
+  /**
     * If an ancestor in this document exists with the given role, return it
     * @param aDescendant Descendant to start search with
     * @param aRole Role to find matching ancestor for
     * @return The ancestor accessible with the given role, or nsnull if no match is found
     */
    static already_AddRefed<nsIAccessible>
      GetAncestorWithRole(nsIAccessible *aDescendant, PRUint32 aRole);
 
Index: accessible/src/base/nsAccessibleEventData.cpp
===================================================================
RCS file: /cvsroot/mozilla/accessible/accessible/src/base/nsAccessibleEventData.cpp,v
retrieving revision 1.28
diff -u -p -8 -r1.28 nsAccessibleEventData.cpp
--- accessible/src/base/nsAccessibleEventData.cpp	19 Feb 2008 11:22:01 -0000	1.28
+++ accessible/src/base/nsAccessibleEventData.cpp	13 Mar 2008 02:36:00 -0000
@@ -52,28 +52,35 @@
 #include "nsIAccessibleText.h"
 #include "nsIContent.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 
 PRBool nsAccEvent::gLastEventFromUserInput = PR_FALSE;
 nsIDOMNode* nsAccEvent::gLastEventNodeWeak = 0;
 
-NS_IMPL_ISUPPORTS1(nsAccEvent, nsIAccessibleEvent)
+NS_IMPL_QUERY_HEAD(nsAccEvent)
+NS_IMPL_QUERY_BODY(nsAccEvent)
+NS_IMPL_QUERY_BODY(nsISupports)
+NS_IMPL_QUERY_BODY(nsIAccessibleEvent)
+NS_IMPL_QUERY_TAIL_GUTS
+
+NS_IMPL_ADDREF(nsAccEvent)
+NS_IMPL_RELEASE(nsAccEvent)
 
 nsAccEvent::nsAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
-                       PRBool aIsAsynch):
-  mEventType(aEventType), mAccessible(aAccessible)
+                       PRBool aIsAsynch, EEventRule aEventRule):
+  mEventType(aEventType), mAccessible(aAccessible), mEventRule(aEventRule)
 {
   CaptureIsFromUserInput(aIsAsynch);
 }
 
 nsAccEvent::nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode,
-                       PRBool aIsAsynch):
-  mEventType(aEventType), mDOMNode(aDOMNode)
+                       PRBool aIsAsynch, EEventRule aEventRule):
+  mEventType(aEventType), mDOMNode(aDOMNode), mEventRule(aEventRule)
 {
   CaptureIsFromUserInput(aIsAsynch);
 }
 
 void nsAccEvent::GetLastEventAttributes(nsIDOMNode *aNode,
                                         nsIPersistentProperties *aAttributes)
 {
   if (aNode == gLastEventNodeWeak) {
@@ -277,16 +284,102 @@ nsAccEvent::GetAccessibleByNode()
       }
     }
   }
 #endif
 
   return accessible;
 }
 
+/* static */
+void
+nsAccEvent::ApplyEventRules(nsCOMArray<nsIAccessibleEvent> &aEventsToFire)
+{
+  PRUint32 numQueuedEvents = aEventsToFire.Count();
+  for (PRInt32 tail = numQueuedEvents - 1; tail >= 0; tail --) {
+    nsRefPtr<nsAccEvent> tailEvent = GetAccEventPtr(aEventsToFire[tail]);
+    switch(tailEvent->mEventRule) {
+      case nsAccEvent::eCoalesceFromSameSubtree:
+      {
+        for (PRInt32 index = 0; index < tail; index ++) {
+          nsRefPtr<nsAccEvent> thisEvent = GetAccEventPtr(aEventsToFire[index]);
+          if (thisEvent->mEventType != tailEvent->mEventType)
+            continue; // Different type
+
+          if (thisEvent->mEventRule == nsAccEvent::eAllowDupes ||
+              thisEvent->mEventRule == nsAccEvent::eDoNotEmit)
+            continue; //  Do not need to check
+
+          if (thisEvent->mDOMNode == tailEvent->mDOMNode) {
+            // Dupe
+            thisEvent->mEventRule = nsAccEvent::eDoNotEmit;
+            continue;
+          }
+          if (nsAccUtils::IsAncestorOf(tailEvent->mDOMNode,
+                                       thisEvent->mDOMNode)) {
+            // thisDOMNode is a descendant of tailDOMNode
+            // Do not emit thisEvent, also apply this result to sibling
+            // nodes of thisDOMNode.
+            thisEvent->mEventRule = nsAccEvent::eDoNotEmit;
+            ApplyToSiblings(aEventsToFire, 0, index, thisEvent->mEventType,
+                            thisEvent->mDOMNode, nsAccEvent::eDoNotEmit);
+            continue;
+          }
+          if (nsAccUtils::IsAncestorOf(thisEvent->mDOMNode,
+                                       tailEvent->mDOMNode)) {
+            // tailDOMNode is a descendant of thisDOMNode
+            // Do not emit tailEvent, also apply this result to sibling
+            // nodes of tailDOMNode.
+            tailEvent->mEventRule = nsAccEvent::eDoNotEmit;
+            ApplyToSiblings(aEventsToFire, 0, tail, tailEvent->mEventType,
+                            tailEvent->mDOMNode, nsAccEvent::eDoNotEmit);
+            break;
+          }
+        } // for (index)
+
+        if (tailEvent->mEventRule != nsAccEvent::eDoNotEmit) {
+          // This event should be emitted
+          // Apply this result to sibling nodes of tailDOMNode
+          ApplyToSiblings(aEventsToFire, 0, tail, tailEvent->mEventType,
+                          tailEvent->mDOMNode, nsAccEvent::eAllowDupes);
+        }
+      } break; // case eCoalesceFromSameSubtree
+
+      case nsAccEvent::eRemoveDupes:
+      {
+        // Check for repeat events.
+        for (PRInt32 index = 0; index < tail; index ++) {
+          nsRefPtr<nsAccEvent> accEvent = GetAccEventPtr(aEventsToFire[index]);
+          if (accEvent->mEventType == tailEvent->mEventType &&
+              accEvent->mEventRule == tailEvent->mEventRule &&
+              accEvent->mDOMNode == tailEvent->mDOMNode) {
+            accEvent->mEventRule = nsAccEvent::eDoNotEmit;
+          }
+        }
+      } break; // case eRemoveDupes
+    } // switch
+  } // for (tail)
+}
+
+/* static */
+void
+nsAccEvent::ApplyToSiblings(nsCOMArray<nsIAccessibleEvent> &aEventsToFire,
+                            PRUint32 aStart, PRUint32 aEnd,
+                             PRUint32 aEventType, nsIDOMNode* aDOMNode,
+                             EEventRule aEventRule)
+{
+  for (PRUint32 index = aStart; index < aEnd; index ++) {
+    nsRefPtr<nsAccEvent> accEvent = GetAccEventPtr(aEventsToFire[index]);
+    if (accEvent->mEventType == aEventType &&
+        accEvent->mEventRule != nsAccEvent::eDoNotEmit &&
+        nsAccUtils::AreSiblings(accEvent->mDOMNode, aDOMNode)) {
+      accEvent->mEventRule = aEventRule;
+    }
+  }
+}
 
 // nsAccStateChangeEvent
 NS_IMPL_ISUPPORTS_INHERITED1(nsAccStateChangeEvent, nsAccEvent,
                              nsIAccessibleStateChangeEvent)
 
 nsAccStateChangeEvent::
   nsAccStateChangeEvent(nsIAccessible *aAccessible,
                         PRUint32 aState, PRBool aIsExtraState,
Index: accessible/src/base/nsAccessibleEventData.h
===================================================================
RCS file: /cvsroot/mozilla/accessible/accessible/src/base/nsAccessibleEventData.h,v
retrieving revision 1.31
diff -u -p -8 -r1.31 nsAccessibleEventData.h
--- accessible/src/base/nsAccessibleEventData.h	19 Feb 2008 11:22:01 -0000	1.31
+++ accessible/src/base/nsAccessibleEventData.h	13 Mar 2008 02:36:00 -0000
@@ -36,56 +36,106 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsAccessibleEventData_H_
 #define _nsAccessibleEventData_H_
 
+#include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
+#include "nsCOMArray.h"
 #include "nsIAccessibleEvent.h"
 #include "nsIAccessible.h"
 #include "nsIAccessibleDocument.h"
 #include "nsIDOMNode.h"
 #include "nsString.h"
 
 class nsIPresShell;
 
+#define NS_ACCEVENT_IMPL_CID                            \
+{  /* 55b89892-a83d-4252-ba78-cbdf53a86936 */           \
+  0x55b89892,                                           \
+  0xa83d,                                               \
+  0x4252,                                               \
+  { 0xba, 0x78, 0xcb, 0xdf, 0x53, 0xa8, 0x69, 0x36 }    \
+}
+
 class nsAccEvent: public nsIAccessibleEvent
 {
 public:
+
+  // Rule for accessible events.
+  // The rule will be applied when flushing pending events.
+  enum EEventRule {
+     // eAllowDupes : More than one event of the same type is allowed.
+     //    This event will always be emitted.
+     eAllowDupes,
+     // eCoalesceFromSameSubtree : For events of the same type from the same
+     //    subtree or the same node, only the umbrelle event on the ancestor
+     //    will be emitted.
+     eCoalesceFromSameSubtree,
+     // eRemoveDupes : For repeat events, only the newest event in queue
+     //    will be emitted.
+     eRemoveDupes,
+     // eDoNotEmit : This event is confirmed as a duplicate, do not emit it.
+     eDoNotEmit
+   };
+
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCEVENT_IMPL_CID)
+
   // Initialize with an nsIAccessible
-  nsAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible, PRBool aIsAsynch = PR_FALSE);
+  nsAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
+             PRBool aIsAsynch = PR_FALSE,
+             EEventRule aEventRule = eRemoveDupes);
   // Initialize with an nsIDOMNode
-  nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode, PRBool aIsAsynch = PR_FALSE);
+  nsAccEvent(PRUint32 aEventType, nsIDOMNode *aDOMNode,
+             PRBool aIsAsynch = PR_FALSE,
+             EEventRule aEventRule = eRemoveDupes);
   virtual ~nsAccEvent() {}
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIACCESSIBLEEVENT
 
   static void GetLastEventAttributes(nsIDOMNode *aNode,
                                      nsIPersistentProperties *aAttributes);
 
 protected:
   already_AddRefed<nsIAccessible> GetAccessibleByNode();
 
   void CaptureIsFromUserInput(PRBool aIsAsynch);
   PRBool mIsFromUserInput;
 
 private:
   PRUint32 mEventType;
+  EEventRule mEventRule;
   nsCOMPtr<nsIAccessible> mAccessible;
   nsCOMPtr<nsIDOMNode> mDOMNode;
   nsCOMPtr<nsIAccessibleDocument> mDocAccessible;
 
   static PRBool gLastEventFromUserInput;
   static nsIDOMNode* gLastEventNodeWeak;
 
 public:
+  static PRUint32 EventType(nsIAccessibleEvent *aAccEvent) {
+    PRUint32 eventType;
+    aAccEvent->GetEventType(&eventType);
+    return eventType;
+  }
+  static EEventRule EventRule(nsIAccessibleEvent *aAccEvent) {
+    nsRefPtr<nsAccEvent> accEvent = GetAccEventPtr(aAccEvent);
+    return accEvent->mEventRule;
+  }
+  static PRBool IsFromUserInput(nsIAccessibleEvent *aAccEvent) {
+    PRBool isFromUserInput;
+    aAccEvent->GetIsFromUserInput(&isFromUserInput);
+    return isFromUserInput;
+  }
+
   static void ResetLastInputState()
    {gLastEventFromUserInput = PR_FALSE; gLastEventNodeWeak = nsnull; }
 
   /**
    * Find and cache the last input state. This will be called automatically
    * for synchronous events. For asynchronous events it should be
    * called from the synchronous code which is the true source of the event,
    * before the event is fired.
@@ -98,18 +148,51 @@ public:
 
   /**
    * The input state was previously stored with the nsIAccessibleEvent,
    * so use that state now -- call this when about to flush an event that 
    * was waiting in an event queue
    */
   static void PrepareForEvent(nsIAccessibleEvent *aEvent,
                               PRBool aForceIsFromUserInput = PR_FALSE);
+
+  /**
+   * Apply event rules to pending events, this method is called in
+   * FlushingPendingEvents().
+   * Result of this method:
+   *   Event rule of filtered events will be set to eDoNotEmit.
+   *   Events with other event rule are good to emit.
+   */
+  static void ApplyEventRules(nsCOMArray<nsIAccessibleEvent> &aEventsToFire);
+
+private:
+  static already_AddRefed<nsAccEvent> GetAccEventPtr(nsIAccessibleEvent *aAccEvent) {
+    nsAccEvent* accEvent = nsnull;
+    aAccEvent->QueryInterface(NS_GET_IID(nsAccEvent), (void**)&accEvent);
+    return accEvent;
+  }
+
+  /**
+   * Apply aEventRule to same type event that from sibling nodes of aDOMNode.
+   * @param aEventsToFire    array of pending events
+   * @param aStart           start index of pending events to be scanned
+   * @param aEnd             end index to be scanned (not included)
+   * @param aEventType       target event type
+   * @param aDOMNode         target are siblings of this node
+   * @param aEventRule       the event rule to be applied
+   *                         (should be eDoNotEmit or eAllowDupes)
+   */
+  static void ApplyToSiblings(nsCOMArray<nsIAccessibleEvent> &aEventsToFire,
+                              PRUint32 aStart, PRUint32 aEnd,
+                              PRUint32 aEventType, nsIDOMNode* aDOMNode,
+                              EEventRule aEventRule);
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(nsAccEvent, NS_ACCEVENT_IMPL_CID)
+
 class nsAccStateChangeEvent: public nsAccEvent,
                              public nsIAccessibleStateChangeEvent
 {
 public:
   nsAccStateChangeEvent(nsIAccessible *aAccessible,
                         PRUint32 aState, PRBool aIsExtraState,
                         PRBool aIsEnabled);
 
Index: accessible/src/base/nsCaretAccessible.cpp
===================================================================
RCS file: /cvsroot/mozilla/accessible/accessible/src/base/nsCaretAccessible.cpp,v
retrieving revision 1.64
diff -u -p -8 -r1.64 nsCaretAccessible.cpp
--- accessible/src/base/nsCaretAccessible.cpp	26 Feb 2008 08:51:11 -0000	1.64
+++ accessible/src/base/nsCaretAccessible.cpp	13 Mar 2008 02:36:00 -0000
@@ -239,17 +239,17 @@ NS_IMETHODIMP nsCaretAccessible::NotifyS
   }
   mLastCaretOffset = caretOffset;
   mLastTextAccessible = textAcc;
 
   nsCOMPtr<nsIAccessibleCaretMoveEvent> event =
     new nsAccCaretMoveEvent(focusNode);
   NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
 
-  return mRootAccessible->FireDelayedAccessibleEvent(event, nsDocAccessible::eRemoveDupes);
+  return mRootAccessible->FireDelayedAccessibleEvent(event);
 }
 
 nsRect
 nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
 {
   nsRect caretRect;
   NS_ENSURE_TRUE(aOutWidget, caretRect);
   *aOutWidget = nsnull;
Index: accessible/src/base/nsDocAccessible.cpp
===================================================================
RCS file: /cvsroot/mozilla/accessible/accessible/src/base/nsDocAccessible.cpp,v
retrieving revision 1.234
diff -u -p -8 -r1.234 nsDocAccessible.cpp
--- accessible/src/base/nsDocAccessible.cpp	29 Feb 2008 15:38:35 -0000	1.234
+++ accessible/src/base/nsDocAccessible.cpp	13 Mar 2008 02:36:01 -0000
@@ -1021,17 +1021,17 @@ nsDocAccessible::AttributeChangedImpl(ns
     // in the wrong namespace or an element that doesn't support it
     InvalidateCacheSubtree(aContent, nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
     return;
   }
   
   if (aAttribute == nsAccessibilityAtoms::alt ||
       aAttribute == nsAccessibilityAtoms::title) {
     FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE,
-                            targetNode, eRemoveDupes);
+                            targetNode);
     return;
   }
 
   if (aAttribute == nsAccessibilityAtoms::selected ||
       aAttribute == nsAccessibilityAtoms::aria_selected) {
     // ARIA or XUL selection
     nsCOMPtr<nsIAccessible> multiSelect = GetMultiSelectFor(targetNode);
     // Multi selects use selection_add and selection_remove
@@ -1043,17 +1043,18 @@ nsDocAccessible::AttributeChangedImpl(ns
       // Need to find the right event to use here, SELECTION_WITHIN would
       // seem right but we had started using it for something else
       nsCOMPtr<nsIAccessNode> multiSelectAccessNode =
         do_QueryInterface(multiSelect);
       nsCOMPtr<nsIDOMNode> multiSelectDOMNode;
       multiSelectAccessNode->GetDOMNode(getter_AddRefs(multiSelectDOMNode));
       NS_ASSERTION(multiSelectDOMNode, "A new accessible without a DOM node!");
       FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_SELECTION_WITHIN,
-                              multiSelectDOMNode, eAllowDupes);
+                              multiSelectDOMNode,
+                              nsAccEvent::eAllowDupes);
 
       static nsIContent::AttrValuesArray strings[] =
         {&nsAccessibilityAtoms::_empty, &nsAccessibilityAtoms::_false, nsnull};
       if (aContent->FindAttrValueIn(kNameSpaceID_None, aAttribute,
                                     strings, eCaseMatters) >= 0) {
         FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_SELECTION_REMOVE,
                                 targetNode);
         return;
@@ -1394,103 +1395,39 @@ nsDocAccessible::CreateTextChangeEventFo
     new nsAccTextChangeEvent(aContainerAccessible, offset, length, aIsInserting, aIsAsynch);
   NS_IF_ADDREF(event);
 
   return event;
 }
   
 nsresult nsDocAccessible::FireDelayedToolkitEvent(PRUint32 aEvent,
                                                   nsIDOMNode *aDOMNode,
-                                                  EDupeEventRule aAllowDupes,
+                                                  nsAccEvent::EEventRule aAllowDupes,
                                                   PRBool aIsAsynch)
 {
   nsCOMPtr<nsIAccessibleEvent> event =
-    new nsAccEvent(aEvent, aDOMNode, aIsAsynch);
+    new nsAccEvent(aEvent, aDOMNode, aIsAsynch, aAllowDupes);
   NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
 
-  return FireDelayedAccessibleEvent(event, aAllowDupes);
+  return FireDelayedAccessibleEvent(event);
 }
 
 nsresult
-nsDocAccessible::FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent,
-                                            EDupeEventRule aAllowDupes)
+nsDocAccessible::FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent)
 {
   NS_ENSURE_TRUE(aEvent, NS_ERROR_FAILURE);
 
-  PRBool isTimerStarted = PR_TRUE;
-  PRInt32 numQueuedEvents = mEventsToFire.Count();
   if (!mFireEventTimer) {
     // Do not yet have a timer going for firing another event.
     mFireEventTimer = do_CreateInstance("@mozilla.org/timer;1");
     NS_ENSURE_TRUE(mFireEventTimer, NS_ERROR_OUT_OF_MEMORY);
   }
 
-  PRUint32 newEventType;
-  aEvent->GetEventType(&newEventType);
-
-  nsCOMPtr<nsIDOMNode> newEventDOMNode;
-  aEvent->GetDOMNode(getter_AddRefs(newEventDOMNode));
-
-  if (numQueuedEvents == 0) {
-    isTimerStarted = PR_FALSE;
-  } else if (aAllowDupes == eCoalesceFromSameSubtree) {
-    // Especially for mutation events, we will define a duplicate event
-    // as one on the same node or on a descendant node.
-    // This prevents a flood of events when a subtree is changed.
-    for (PRInt32 index = 0; index < numQueuedEvents; index ++) {
-      nsIAccessibleEvent *accessibleEvent = mEventsToFire[index];
-      NS_ASSERTION(accessibleEvent, "Array item is not an accessible event");
-      if (!accessibleEvent) {
-        continue;
-      }
-      PRUint32 eventType;
-      accessibleEvent->GetEventType(&eventType);
-      if (eventType == newEventType) {
-        nsCOMPtr<nsIDOMNode> domNode;
-        accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
-        if (newEventDOMNode == domNode || nsAccUtils::IsAncestorOf(newEventDOMNode, domNode)) {
-          mEventsToFire.RemoveObjectAt(index);
-          // The other event is the same type, but in a descendant of this
-          // event, so remove that one. The umbrella event in the ancestor
-          // is already enough
-          -- index;
-          -- numQueuedEvents;
-        }
-        else if (nsAccUtils::IsAncestorOf(domNode, newEventDOMNode)) {
-          // There is a better SHOW/HIDE event (it's in an ancestor)
-          return NS_OK;
-        }
-      }    
-    }
-  } else if (aAllowDupes == eRemoveDupes) {
-    // Check for repeat events. If a redundant event exists remove
-    // original and put the new event at the end of the queue
-    // so it is fired after the others
-    for (PRInt32 index = 0; index < numQueuedEvents; index ++) {
-      nsIAccessibleEvent *accessibleEvent = mEventsToFire[index];
-      NS_ASSERTION(accessibleEvent, "Array item is not an accessible event");
-      if (!accessibleEvent) {
-        continue;
-      }
-      PRUint32 eventType;
-      accessibleEvent->GetEventType(&eventType);
-      if (eventType == newEventType) {
-        nsCOMPtr<nsIDOMNode> domNode;
-        accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
-        if (domNode == newEventDOMNode) {
-          mEventsToFire.RemoveObjectAt(index);
-          -- index;
-          -- numQueuedEvents;
-        }
-      }
-    }
-  }
-
   mEventsToFire.AppendObject(aEvent);
-  if (!isTimerStarted) {
+  if (mEventsToFire.Count() == 1) {
     // This is be the first delayed event in queue, start timer
     // so that event gets fired via FlushEventsCallback
     NS_ADDREF_THIS(); // Kung fu death grip to prevent crash in callback
     mFireEventTimer->InitWithFuncCallback(FlushEventsCallback,
                                           static_cast<nsPIAccessibleDocument*>(this),
                                           0, nsITimer::TYPE_ONE_SHOT);
   }
 
@@ -1499,30 +1436,32 @@ nsDocAccessible::FireDelayedAccessibleEv
 
 NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
 {
   PRUint32 length = mEventsToFire.Count();
   NS_ASSERTION(length, "How did we get here without events to fire?");
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   if (!presShell)
     length = 0; // The doc is now shut down, don't fire events in it anymore
-  PRUint32 index;
-  for (index = 0; index < length; index ++) {
+  else
+    nsAccEvent::ApplyEventRules(mEventsToFire);
+  
+  for (PRUint32 index = 0; index < length; index ++) {
     nsCOMPtr<nsIAccessibleEvent> accessibleEvent(
       do_QueryInterface(mEventsToFire[index]));
-    NS_ASSERTION(accessibleEvent, "Array item is not an accessible event");
+
+    if (nsAccEvent::EventRule(accessibleEvent) == nsAccEvent::eDoNotEmit)
+      continue;
 
     nsCOMPtr<nsIAccessible> accessible;
     accessibleEvent->GetAccessible(getter_AddRefs(accessible));
     nsCOMPtr<nsIDOMNode> domNode;
     accessibleEvent->GetDOMNode(getter_AddRefs(domNode));
-    PRUint32 eventType;
-    accessibleEvent->GetEventType(&eventType);
-    PRBool isFromUserInput;
-    accessibleEvent->GetIsFromUserInput(&isFromUserInput);
+    PRUint32 eventType = nsAccEvent::EventType(accessibleEvent);
+    PRBool isFromUserInput = nsAccEvent::IsFromUserInput(accessibleEvent);
 
     if (domNode == gLastFocusedNode &&
         eventType == nsIAccessibleEvent::EVENT_ASYNCH_HIDE || 
         eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) {
       // If frame type didn't change for this event, then we don't actually need to invalidate
       // However, we only keep track of the old frame type for the focus, where it's very
       // important not to destroy and recreate the accessible for minor style changes,
       // such as a:focus { overflow: scroll; }
@@ -1935,33 +1874,35 @@ NS_IMETHODIMP nsDocAccessible::Invalidat
     // 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,
     // the assistive technology may receive the event and then retrieve
     // nsIAccessibleStates::STATE_INVISIBLE for the event's accessible object.
     PRUint32 additionEvent = isAsynch ? nsIAccessibleEvent::EVENT_ASYNCH_SHOW :
                                         nsIAccessibleEvent::EVENT_DOM_CREATE;
     FireDelayedToolkitEvent(additionEvent, childNode,
-                            eCoalesceFromSameSubtree, isAsynch);
+                            nsAccEvent::eCoalesceFromSameSubtree,
+                            isAsynch);
 
     // Check to see change occured in an ARIA menu, and fire
     // an EVENT_MENUPOPUP_START if it did.
     nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(childNode);
     if (roleMapEntry && roleMapEntry->role == nsIAccessibleRole::ROLE_MENUPOPUP) {
       FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
-                              childNode, eRemoveDupes, isAsynch);
+                              childNode, nsAccEvent::eRemoveDupes,
+                              isAsynch);
     }
 
     // Check to see if change occured inside an alert, and fire an EVENT_ALERT if it did
     nsIContent *ancestor = aChild;
     while (PR_TRUE) {
       if (roleMapEntry && roleMapEntry->role == nsIAccessibleRole::ROLE_ALERT) {
         nsCOMPtr<nsIDOMNode> alertNode(do_QueryInterface(ancestor));
         FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_ALERT, alertNode,
-                                eRemoveDupes, isAsynch);
+                                nsAccEvent::eRemoveDupes, isAsynch);
         break;
       }
       ancestor = ancestor->GetParent();
       nsCOMPtr<nsIDOMNode> ancestorNode = do_QueryInterface(ancestor);
       if (!ancestorNode) {
         break;
       }
       roleMapEntry = nsAccUtils::GetRoleMapEntry(ancestorNode);
@@ -1969,19 +1910,20 @@ NS_IMETHODIMP nsDocAccessible::Invalidat
   }
 
   if (!isShowing) {
     // Fire an event so the assistive technology knows the children have changed
     // This is only used by older MSAA clients. Newer ones should derive this
     // from SHOW and HIDE so that they don't fetch extra objects
     if (childAccessible) {
       nsCOMPtr<nsIAccessibleEvent> reorderEvent =
-        new nsAccEvent(nsIAccessibleEvent::EVENT_REORDER, containerAccessible, isAsynch);
+        new nsAccEvent(nsIAccessibleEvent::EVENT_REORDER, containerAccessible,
+                       isAsynch, nsAccEvent::eCoalesceFromSameSubtree);
       NS_ENSURE_TRUE(reorderEvent, NS_ERROR_OUT_OF_MEMORY);
-      FireDelayedAccessibleEvent(reorderEvent, eCoalesceFromSameSubtree);
+      FireDelayedAccessibleEvent(reorderEvent);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocAccessible::GetAccessibleInParentChain(nsIDOMNode *aNode,
@@ -2047,23 +1989,24 @@ nsDocAccessible::FireShowHideEvents(nsID
 
   if (accessible) {
     // Found an accessible, so fire the show/hide on it and don't
     // look further into this subtree
     PRBool isAsynch = aEventType == nsIAccessibleEvent::EVENT_ASYNCH_HIDE ||
                       aEventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW;
 
     nsCOMPtr<nsIAccessibleEvent> event =
-      new nsAccEvent(aEventType, accessible, isAsynch);
+      new nsAccEvent(aEventType, accessible, isAsynch,
+                     nsAccEvent::eCoalesceFromSameSubtree);
     NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
     if (aForceIsFromUserInput) {
       nsAccEvent::PrepareForEvent(event, aForceIsFromUserInput);
     }
     if (aDelay) {
-      return FireDelayedAccessibleEvent(event, eCoalesceFromSameSubtree);
+      return FireDelayedAccessibleEvent(event);
     }
     return FireAccessibleEvent(event);
   }
 
   // Could not find accessible to show hide yet, so fire on any
   // accessible descendants in this subtree
   nsCOMPtr<nsIContent> content(do_QueryInterface(aDOMNode));
   PRUint32 count = content->GetChildCount();
Index: accessible/src/base/nsDocAccessible.h
===================================================================
RCS file: /cvsroot/mozilla/accessible/accessible/src/base/nsDocAccessible.h,v
retrieving revision 1.76
diff -u -p -8 -r1.76 nsDocAccessible.h
--- accessible/src/base/nsDocAccessible.h	26 Feb 2008 14:19:52 -0000	1.76
+++ accessible/src/base/nsDocAccessible.h	13 Mar 2008 02:36:01 -0000
@@ -96,46 +96,40 @@ class nsDocAccessible : public nsHyperTe
     NS_IMETHOD Init();
 
     // nsPIAccessNode
     NS_IMETHOD_(nsIFrame *) GetFrame(void);
 
     // nsIAccessibleText
     NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
 
-    enum EDupeEventRule { eAllowDupes, eCoalesceFromSameSubtree, eRemoveDupes };
-
     /**
       * Non-virtual method to fire a delayed event after a 0 length timeout
       *
       * @param aEvent - the nsIAccessibleEvent event type
       * @param aDOMNode - DOM node the accesible event should be fired for
       * @param aAllowDupes - eAllowDupes: more than one event of the same type is allowed. 
       *                      eCoalesceFromSameSubtree: if two events are in the same subtree,
       *                                                only the event on ancestor is used
       *                      eRemoveDupes (default): events of the same type are discarded
       *                                              (the last one is used)
       *
       * @param aIsAsynch - set to PR_TRUE if this is not being called from code
       *                    synchronous with a DOM event
       */
     nsresult FireDelayedToolkitEvent(PRUint32 aEvent, nsIDOMNode *aDOMNode,
-                                     EDupeEventRule aAllowDupes = eRemoveDupes,
+                                     nsAccEvent::EEventRule aAllowDupes = nsAccEvent::eRemoveDupes,
                                      PRBool aIsAsynch = PR_FALSE);
 
     /**
      * Fire accessible event in timeout.
      *
      * @param aEvent - the event to fire
-     * @param aAllowDupes - if false then delayed events of the same type and
-     *                      for the same DOM node in the event queue won't
-     *                      be fired.
      */
-    nsresult FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent,
-                                        EDupeEventRule aAllowDupes = eRemoveDupes);
+    nsresult FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent);
 
     void ShutdownChildDocuments(nsIDocShellTreeItem *aStart);
 
   protected:
     virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
     virtual nsresult AddEventListeners();
     virtual nsresult RemoveEventListeners();
     void AddScrollListener();
Index: accessible/src/base/nsRootAccessible.cpp
===================================================================
RCS file: /cvsroot/mozilla/accessible/accessible/src/base/nsRootAccessible.cpp,v
retrieving revision 1.261
diff -u -p -8 -r1.261 nsRootAccessible.cpp
--- accessible/src/base/nsRootAccessible.cpp	6 Mar 2008 03:43:51 -0000	1.261
+++ accessible/src/base/nsRootAccessible.cpp	13 Mar 2008 02:36:02 -0000
@@ -403,18 +403,17 @@ void nsRootAccessible::TryFireEarlyLoadE
       return;
     }
   }
   nsCOMPtr<nsIDocShellTreeItem> rootContentTreeItem;
   treeItem->GetSameTypeRootTreeItem(getter_AddRefs(rootContentTreeItem));
   NS_ASSERTION(rootContentTreeItem, "No root content tree item");
   if (rootContentTreeItem == treeItem) {
     // No frames or iframes, so we can fire the doc load finished event early
-    FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode,
-                            eRemoveDupes);
+    FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode);
   }
 }
 
 PRBool nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
                                                   nsIDOMNode *aNode,
                                                   nsIDOMEvent *aFocusEvent,
                                                   PRBool aForceEvent,
                                                   PRBool aIsAsynch)
@@ -498,19 +497,20 @@ PRBool nsRootAccessible::FireAccessibleF
             nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENU_START, menuBarAccessible);
           }
         }
       }
     }
   }
   else if (mCurrentARIAMenubar) {
     nsCOMPtr<nsIAccessibleEvent> menuEndEvent =
-      new nsAccEvent(nsIAccessibleEvent::EVENT_MENU_END, mCurrentARIAMenubar, PR_FALSE);
+      new nsAccEvent(nsIAccessibleEvent::EVENT_MENU_END, mCurrentARIAMenubar,
+                     PR_FALSE, nsAccEvent::eAllowDupes);
     if (menuEndEvent) {
-      FireDelayedAccessibleEvent(menuEndEvent, eAllowDupes);
+      FireDelayedAccessibleEvent(menuEndEvent);
     }
     mCurrentARIAMenubar = nsnull;
   }
 
   NS_IF_RELEASE(gLastFocusedNode);
   gLastFocusedNode = finalFocusNode;
   NS_IF_ADDREF(gLastFocusedNode);
 
@@ -531,17 +531,18 @@ PRBool nsRootAccessible::FireAccessibleF
       // and that's what we care about
       // Make sure we never fire focus for the nsRootAccessible (mDOMNode)
       
 return PR_FALSE;
     }
   }
 
   FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_FOCUS,
-                          finalFocusNode, eRemoveDupes, aIsAsynch);
+                          finalFocusNode, nsAccEvent::eRemoveDupes,
+                          aIsAsynch);
 
   return PR_TRUE;
 }
 
 void nsRootAccessible::FireCurrentFocusEvent()
 {
   nsCOMPtr<nsIDOMNode> focusedNode = GetCurrentFocus();
   if (!focusedNode) {



Index: .cvsignore
===================================================================
RCS file: /cvs/extras/rpms/xulrunner/devel/.cvsignore,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -r1.40 -r1.41
--- .cvsignore	16 Mar 2008 02:24:20 -0000	1.40
+++ .cvsignore	17 Mar 2008 03:27:56 -0000	1.41
@@ -1 +1 @@
-mozilla-20080315.tar.bz2
+mozilla-20080316.tar.bz2


Index: sources
===================================================================
RCS file: /cvs/extras/rpms/xulrunner/devel/sources,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- sources	16 Mar 2008 02:24:20 -0000	1.41
+++ sources	17 Mar 2008 03:27:56 -0000	1.42
@@ -1 +1 @@
-d5302f5a63f722a4bfb4cb3566c1d70e  mozilla-20080315.tar.bz2
+c9e524654747ccfa7ce396244e08e674  mozilla-20080316.tar.bz2


Index: xulrunner.spec
===================================================================
RCS file: /cvs/extras/rpms/xulrunner/devel/xulrunner.spec,v
retrieving revision 1.96
retrieving revision 1.97
diff -u -r1.96 -r1.97
--- xulrunner.spec	16 Mar 2008 02:24:20 -0000	1.96
+++ xulrunner.spec	17 Mar 2008 03:27:56 -0000	1.97
@@ -7,14 +7,14 @@
 %define version_internal  1.9pre
 
 %if ! %{official_branding}
-%define cvsdate 20080315
+%define cvsdate 20080316
 %define nightly .cvs%{cvsdate}
 %endif
 
 Summary:        XUL Runtime for Gecko Applications
 Name:           xulrunner
 Version:        1.9
-Release:        0.42%{?nightly}%{?dist}
+Release:        0.43%{?nightly}%{?dist}
 URL:            http://www.mozilla.org/projects/xulrunner/
 License:        MPLv1.1 or GPLv2+ or LGPLv2+
 Group:          Applications/Internet
@@ -41,6 +41,7 @@
 # local bugfixes
 Patch41:        firefox-2.0.0.4-undo-uriloader.patch
 Patch42:        firefox-1.1-uriloader.patch
+Patch43:        xulrunner-a11y.patch
 
 # font system fixes
 
@@ -125,6 +126,8 @@
 %patch5   -p1
 %patch6   -p1 -b .ver
 
+%patch43 -p0 -b .a11y
+
 %patch107 -p1 -b .pk
 
 
@@ -407,6 +410,10 @@
 #---------------------------------------------------------------------
 
 %changelog
+* Sat Mar 16 2008 Christopher Aillon <caillon at redhat.com> 1.9-0.43
+- Update to latest trunk (2008-03-16)
+- Add patch to negate a11y slowdown on some pages (#431162)
+
 * Sat Mar 15 2008 Christopher Aillon <caillon at redhat.com> 1.9-0.42
 - Update to latest trunk (2008-03-15)
 




More information about the fedora-extras-commits mailing list