Bug 614800 - coalesce text attribute change events and fire caret move event for the document where event occurred, r=davidb, marcoz, a=davidb
authorAlexander Surkov <surkov.alexander@gmail.com>
Tue, 30 Nov 2010 00:03:29 +0800
changeset 58325 ff0e38477a8db97a3f59cf9fc9e7e8c6e7897fa4
parent 58324 21762517cdea401bd9a1399764a320adc976c6f6
child 58326 6f14ee0618153673f08cc30c9451abd189fa4ba6
push id17245
push usersurkov.alexander@gmail.com
push dateMon, 29 Nov 2010 16:04:07 +0000
treeherdermozilla-central@ff0e38477a8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdavidb, marcoz, davidb
bugs614800
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 614800 - coalesce text attribute change events and fire caret move event for the document where event occurred, r=davidb, marcoz, a=davidb
accessible/src/base/nsAccUtils.cpp
accessible/src/base/nsAccUtils.h
accessible/src/base/nsCaretAccessible.cpp
accessible/src/base/nsCaretAccessible.h
accessible/tests/mochitest/test_text_caret.html
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -400,18 +400,17 @@ PRBool
 nsAccUtils::IsARIASelected(nsAccessible *aAccessible)
 {
   return aAccessible->GetContent()->
     AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::aria_selected,
                 nsAccessibilityAtoms::_true, eCaseMatters);
 }
 
 already_AddRefed<nsHyperTextAccessible>
-nsAccUtils::GetTextAccessibleFromSelection(nsISelection *aSelection,
-                                           nsINode **aNode)
+nsAccUtils::GetTextAccessibleFromSelection(nsISelection* aSelection)
 {
   // Get accessible from selection's focus DOM point (the DOM point where
   // selection is ended).
 
   nsCOMPtr<nsIDOMNode> focusDOMNode;
   aSelection->GetFocusNode(getter_AddRefs(focusDOMNode));
   if (!focusDOMNode)
     return nsnull;
@@ -430,22 +429,19 @@ nsAccUtils::GetTextAccessibleFromSelecti
   if (!accessible) {
     NS_NOTREACHED("No nsIAccessibleText for selection change event!");
     return nsnull;
   }
 
   do {
     nsHyperTextAccessible* textAcc = nsnull;
     CallQueryInterface(accessible, &textAcc);
-    if (textAcc) {
-      if (aNode)
-        NS_ADDREF(*aNode = accessible->GetNode());
+    if (textAcc)
+      return textAcc;
 
-      return textAcc;
-    }
   } while (accessible = accessible->GetParent());
 
   NS_NOTREACHED("We must reach document accessible implementing nsIAccessibleText!");
   return nsnull;
 }
 
 nsresult
 nsAccUtils::ConvertToScreenCoords(PRInt32 aX, PRInt32 aY,
--- a/accessible/src/base/nsAccUtils.h
+++ b/accessible/src/base/nsAccUtils.h
@@ -218,22 +218,20 @@ public:
    */
   static PRBool IsARIASelected(nsAccessible *aAccessible);
 
   /**
    * Return text accessible containing focus point of the given selection.
    * Used for normal and misspelling selection changes processing.
    *
    * @param aSelection  [in] the given selection
-   * @param aNode       [out, optional] the DOM node of text accessible
    * @return            text accessible
    */
   static already_AddRefed<nsHyperTextAccessible>
-    GetTextAccessibleFromSelection(nsISelection *aSelection,
-                                   nsINode **aNode = nsnull);
+    GetTextAccessibleFromSelection(nsISelection* aSelection);
 
   /**
    * Converts the given coordinates to coordinates relative screen.
    *
    * @param aX               [in] the given x coord
    * @param aY               [in] the given y coord
    * @param aCoordinateType  [in] specifies coordinates origin (refer to
    *                         nsIAccessibleCoordinateType)
--- a/accessible/src/base/nsCaretAccessible.cpp
+++ b/accessible/src/base/nsCaretAccessible.cpp
@@ -196,104 +196,102 @@ nsCaretAccessible::RemoveDocSelectionLis
                        getter_AddRefs(spellcheckSel));
   selPrivate = do_QueryInterface(spellcheckSel);
   NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE);
 
   return selPrivate->RemoveSelectionListener(this);
 }
 
 NS_IMETHODIMP
-nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc,
-                                          nsISelection *aSel,
+nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
+                                          nsISelection* aSelection,
                                           PRInt16 aReason)
 {
-  NS_ENSURE_ARG(aDoc);
+  NS_ENSURE_ARG(aDOMDocument);
+  NS_ENSURE_STATE(mRootAccessible);
 
-  nsCOMPtr<nsIDocument> document(do_QueryInterface(aDoc));
-  nsDocAccessible *docAccessible = GetAccService()->GetDocAccessible(document);
+  nsCOMPtr<nsIDocument> documentNode(do_QueryInterface(aDOMDocument));
+  nsDocAccessible* document = GetAccService()->GetDocAccessible(documentNode);
 
   // Don't fire events until document is loaded.
-  if (!docAccessible || !docAccessible->IsContentLoaded())
+  if (!document || !document->IsContentLoaded())
     return NS_OK;
 
-  nsCOMPtr<nsISelection2> sel2(do_QueryInterface(aSel));
+  nsCOMPtr<nsISelection2> sel2(do_QueryInterface(aSelection));
 
   PRInt16 type = 0;
   sel2->GetType(&type);
 
   if (type == nsISelectionController::SELECTION_NORMAL)
-    return NormalSelectionChanged(aDoc, aSel);
+    NormalSelectionChanged(document, aSelection);
 
-  if (type == nsISelectionController::SELECTION_SPELLCHECK)
-    return SpellcheckSelectionChanged(aDoc, aSel);
+  else if (type == nsISelectionController::SELECTION_SPELLCHECK)
+    SpellcheckSelectionChanged(document, aSelection);
 
   return NS_OK;
 }
 
-nsresult
-nsCaretAccessible::NormalSelectionChanged(nsIDOMDocument *aDoc,
-                                          nsISelection *aSel)
+void
+nsCaretAccessible::NormalSelectionChanged(nsDocAccessible* aDocument,
+                                          nsISelection* aSelection)
 {
-  NS_ENSURE_TRUE(mRootAccessible, NS_ERROR_FAILURE);
-
-  mLastUsedSelection = do_GetWeakReference(aSel);
+  mLastUsedSelection = do_GetWeakReference(aSelection);
 
   PRInt32 rangeCount = 0;
-  nsresult rv = aSel->GetRangeCount(&rangeCount);
-  NS_ENSURE_SUCCESS(rv, rv);
-
+  aSelection->GetRangeCount(&rangeCount);
   if (rangeCount == 0) {
     mLastTextAccessible = nsnull;
-    return NS_OK; // No selection
+    return; // No selection
   }
 
-  nsCOMPtr<nsINode> textNode;
   nsRefPtr<nsHyperTextAccessible> textAcc =
-    nsAccUtils::GetTextAccessibleFromSelection(aSel, getter_AddRefs(textNode));
-  NS_ENSURE_STATE(textAcc);
+    nsAccUtils::GetTextAccessibleFromSelection(aSelection);
+  if (!textAcc)
+    return;
 
-  PRInt32 caretOffset;
-  rv = textAcc->GetCaretOffset(&caretOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
+  PRInt32 caretOffset = -1;
+  nsresult rv = textAcc->GetCaretOffset(&caretOffset);
+  if (NS_FAILED(rv))
+    return;
 
   if (textAcc == mLastTextAccessible && caretOffset == mLastCaretOffset) {
-    PRInt32 selectionCount;
+    PRInt32 selectionCount = 0;
     textAcc->GetSelectionCount(&selectionCount);   // Don't swallow similar events when selecting text
-    if (!selectionCount) {
-      return NS_OK;  // Swallow duplicate caret event
-    }
+    if (!selectionCount)
+      return;  // Swallow duplicate caret event
   }
+
   mLastCaretOffset = caretOffset;
   mLastTextAccessible.swap(textAcc);
 
-  nsRefPtr<AccEvent> event = new AccCaretMoveEvent(textNode);
-  NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
-
-  return mRootAccessible->FireDelayedAccessibleEvent(event);
+  nsRefPtr<AccEvent> event =
+    new AccCaretMoveEvent(mLastTextAccessible->GetNode());
+  if (event)
+    aDocument->FireDelayedAccessibleEvent(event);
 }
 
-nsresult
-nsCaretAccessible::SpellcheckSelectionChanged(nsIDOMDocument *aDoc,
-                                              nsISelection *aSel)
+void
+nsCaretAccessible::SpellcheckSelectionChanged(nsDocAccessible* aDocument,
+                                              nsISelection* aSelection)
 {
   // XXX: fire an event for accessible of focus node of the selection. If
   // spellchecking is enabled then we will fire the number of events for
   // the same accessible for newly appended range of the selection (for every
   // misspelled word). If spellchecking is disabled (for example,
   // @spellcheck="false" on html:body) then we won't fire any event.
 
   nsRefPtr<nsHyperTextAccessible> textAcc =
-    nsAccUtils::GetTextAccessibleFromSelection(aSel);
-  NS_ENSURE_STATE(textAcc);
+    nsAccUtils::GetTextAccessibleFromSelection(aSelection);
+  if (!textAcc)
+    return;
 
   nsRefPtr<AccEvent> event =
     new AccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED, textAcc);
-
-  nsEventShell::FireEvent(event);
-  return NS_OK;
+  if (event)
+    aDocument->FireDelayedAccessibleEvent(event);
 }
 
 nsIntRect
 nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget)
 {
   nsIntRect caretRect;
   NS_ENSURE_TRUE(aOutWidget, caretRect);
   *aOutWidget = nsnull;
--- a/accessible/src/base/nsCaretAccessible.h
+++ b/accessible/src/base/nsCaretAccessible.h
@@ -111,18 +111,28 @@ public:
    * the document, and in any case it is unavailable from the doc after a pagehide.
    * @param aShell   PresShell for document to no longer listen to selection events from.
    */
   nsresult RemoveDocSelectionListener(nsIPresShell *aShell);
 
   nsIntRect GetCaretRect(nsIWidget **aOutWidget);
 
 protected:
-  nsresult NormalSelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel);
-  nsresult SpellcheckSelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel);
+  /**
+   * Process normal selection change and fire caret move event.
+   */
+  void NormalSelectionChanged(nsDocAccessible* aDocument,
+                              nsISelection* aSelection);
+
+  /**
+   * Process spellcheck selection change and fire text attribute changed event
+   * for invalid text attribute.
+   */
+  void SpellcheckSelectionChanged(nsDocAccessible* aDocument,
+                                  nsISelection* aSelection);
 
   /**
    * Return selection controller for the given node.
    */
   already_AddRefed<nsISelectionController>
     GetSelectionControllerForNode(nsIContent *aNode);
 
 private:
--- a/accessible/tests/mochitest/test_text_caret.html
+++ b/accessible/tests/mochitest/test_text_caret.html
@@ -38,25 +38,26 @@
      */
     function setCaretOffsetInvoker(aID, aOffset)
     {
       this.target = getAccessible(aID, [nsIAccessibleText]);
 
       this.invoke = function setCaretOffsetInvoker_invoke()
       {
         this.target.caretOffset = aOffset;
+        todo(false, "Enable focus event handling when bug 422744 is fixed.");
       }
 
       this.getID = function setCaretOffsetInvoker_getID()
       {
-        "nsIAccessibleText::caretOffset test"
+        return "nsIAccessibleText::caretOffset test";
       }
 
       this.eventSeq = [
-        new invokerChecker(EVENT_FOCUS, this.target),
+        // new invokerChecker(EVENT_FOCUS, this.target),
         new caretMovedChecker(this.target, aOffset)
       ];
     }
 
     /**
      * Do tests.
      */
     var gQueue = null;