Bug 756502 - Added reason to pivot change notifications. r=davidb
authorEitan Isaacson <eitan@monotonous.org>
Wed, 20 Jun 2012 14:07:51 -0700
changeset 97201 60468d1cc060cb9c2ef2c03df4c34d3b8b45885c
parent 97200 30a83fad22e58908eeb89f89c86c2838bc3afaf5
child 97202 f08d99730f3305576b1d4e07859e30baf40e33a9
push id22962
push useremorley@mozilla.com
push dateThu, 21 Jun 2012 10:59:14 +0000
treeherdermozilla-central@10e019421e6b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdavidb
bugs756502
milestone16.0a1
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 756502 - Added reason to pivot change notifications. r=davidb
accessible/public/nsIAccessibleEvent.idl
accessible/public/nsIAccessiblePivot.idl
accessible/src/base/AccEvent.cpp
accessible/src/base/AccEvent.h
accessible/src/base/nsAccessiblePivot.cpp
accessible/src/base/nsAccessiblePivot.h
accessible/src/generic/DocAccessible.cpp
accessible/src/xpcom/nsAccEvent.cpp
accessible/tests/mochitest/pivot.js
--- a/accessible/public/nsIAccessibleEvent.idl
+++ b/accessible/public/nsIAccessibleEvent.idl
@@ -554,9 +554,14 @@ interface nsIAccessibleVirtualCursorChan
    * Previous start offset of pivot. -1 if none.
    */
   readonly attribute long oldStartOffset;
 
   /**
    * Previous end offset of pivot. -1 if none.
    */
   readonly attribute long oldEndOffset;
+
+  /**
+   * Reason for virtual cursor move.
+   */
+  readonly attribute short reason;
 };
--- a/accessible/public/nsIAccessiblePivot.idl
+++ b/accessible/public/nsIAccessiblePivot.idl
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 typedef short TextBoundaryType;
+typedef short PivotMoveReason;
 
 interface nsIAccessible;
 interface nsIAccessibleText;
 interface nsIAccessibleTraversalRule;
 interface nsIAccessiblePivotObserver;
 
 /**
  * The pivot interface encapsulates a reference to a single place in an accessible
@@ -22,16 +23,24 @@ interface nsIAccessiblePivotObserver;
 [scriptable, uuid(15ff23de-879e-47ea-b536-6532466108c5)]
 interface nsIAccessiblePivot : nsISupports
 {
   const TextBoundaryType CHAR_BOUNDARY = 0;
   const TextBoundaryType WORD_BOUNDARY = 1;
   const TextBoundaryType LINE_BOUNDARY = 2;
   const TextBoundaryType ATTRIBUTE_RANGE_BOUNDARY = 3;
 
+  const PivotMoveReason REASON_NONE = 0;
+  const PivotMoveReason REASON_NEXT = 1;
+  const PivotMoveReason REASON_PREV = 2;
+  const PivotMoveReason REASON_FIRST = 3;
+  const PivotMoveReason REASON_LAST = 4;
+  const PivotMoveReason REASON_TEXT = 5;
+  const PivotMoveReason REASON_POINT = 6;
+
   /**
    * The accessible the pivot is currently pointed at.
    */
   attribute nsIAccessible position;
 
   /**
    * The root of the subtree in which the pivot traverses.
    */
@@ -159,20 +168,22 @@ interface nsIAccessiblePivotObserver : n
 {
   /**
    * Called when the pivot changes.
    *
    * @param aPivot         [in] the pivot that has changed.
    * @param aOldAccessible [in] the old pivot position before the change, or null.
    * @param aOldStart      [in] the old start offset, or -1.
    * @param aOldEnd        [in] the old end offset, or -1.
+   * @param aReason        [in] the reason for the pivot change.
    */
   void onPivotChanged(in nsIAccessiblePivot aPivot,
                       in nsIAccessible aOldAccessible,
-                      in long aOldStart, in long aOldEnd);
+                      in long aOldStart, in long aOldEnd,
+                      in PivotMoveReason aReason);
 };
 
 [scriptable, uuid(307d98b6-dba9-49cf-ba17-ef8b053044eb)]
 interface nsIAccessibleTraversalRule : nsISupports
 {
   /* Ignore this accessible object */
   const unsigned short FILTER_IGNORE = 0x0;
   /* Accept this accessible object */
--- a/accessible/src/base/AccEvent.cpp
+++ b/accessible/src/base/AccEvent.cpp
@@ -363,19 +363,21 @@ AccTableChangeEvent::CreateXPCOMObject()
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccVCChangeEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 AccVCChangeEvent::
   AccVCChangeEvent(Accessible* aAccessible,
                    nsIAccessible* aOldAccessible,
-                   PRInt32 aOldStart, PRInt32 aOldEnd) :
+                   PRInt32 aOldStart, PRInt32 aOldEnd,
+                   PRInt16 aReason) :
     AccEvent(::nsIAccessibleEvent::EVENT_VIRTUALCURSOR_CHANGED, aAccessible),
-    mOldAccessible(aOldAccessible), mOldStart(aOldStart), mOldEnd(aOldEnd)
+    mOldAccessible(aOldAccessible), mOldStart(aOldStart), mOldEnd(aOldEnd),
+    mReason(aReason)
 {
 }
 
 already_AddRefed<nsAccEvent>
 AccVCChangeEvent::CreateXPCOMObject()
 {
   nsAccEvent* event = new nsAccVirtualCursorChangeEvent(this);
   NS_ADDREF(event);
--- a/accessible/src/base/AccEvent.h
+++ b/accessible/src/base/AccEvent.h
@@ -368,38 +368,41 @@ private:
 /**
  * Accessible virtual cursor change event.
  */
 class AccVCChangeEvent : public AccEvent
 {
 public:
   AccVCChangeEvent(Accessible* aAccessible,
                    nsIAccessible* aOldAccessible,
-                   PRInt32 aOldStart, PRInt32 aOldEnd);
+                   PRInt32 aOldStart, PRInt32 aOldEnd,
+                   PRInt16 aReason);
 
   virtual ~AccVCChangeEvent() { }
 
   // AccEvent
   virtual already_AddRefed<nsAccEvent> CreateXPCOMObject();
 
   static const EventGroup kEventGroup = eVirtualCursorChangeEvent;
   virtual unsigned int GetEventGroups() const
   {
     return AccEvent::GetEventGroups() | (1U << eVirtualCursorChangeEvent);
   }
 
   // AccTableChangeEvent
   nsIAccessible* OldAccessible() const { return mOldAccessible; }
   PRInt32 OldStartOffset() const { return mOldStart; }
   PRInt32 OldEndOffset() const { return mOldEnd; }
+  PRInt32 Reason() const { return mReason; }
 
 private:
   nsRefPtr<nsIAccessible> mOldAccessible;
   PRInt32 mOldStart;
   PRInt32 mOldEnd;
+  PRInt16 mReason;
 };
 
 /**
  * Downcast the generic accessible event object to derived type.
  */
 class downcast_accEvent
 {
 public:
--- a/accessible/src/base/nsAccessiblePivot.cpp
+++ b/accessible/src/base/nsAccessiblePivot.cpp
@@ -113,17 +113,18 @@ nsAccessiblePivot::SetPosition(nsIAccess
     if (!secondPosition || !IsRootDescendant(secondPosition))
       return NS_ERROR_INVALID_ARG;
   }
 
   // Swap old position with new position, saves us an AddRef/Release.
   mPosition.swap(secondPosition);
   PRInt32 oldStart = mStartOffset, oldEnd = mEndOffset;
   mStartOffset = mEndOffset = -1;
-  NotifyOfPivotChange(secondPosition, oldStart, oldEnd);
+  NotifyOfPivotChange(secondPosition, oldStart, oldEnd,
+                      nsIAccessiblePivot::REASON_NONE);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessiblePivot::GetStartOffset(PRInt32* aStartOffset)
 {
   NS_ENSURE_ARG_POINTER(aStartOffset);
@@ -171,17 +172,18 @@ nsAccessiblePivot::SetTextRange(nsIAcces
 
   PRInt32 oldStart = mStartOffset, oldEnd = mEndOffset;
   mStartOffset = aStartOffset;
   mEndOffset = aEndOffset;
 
   nsRefPtr<Accessible> oldPosition = mPosition.forget();
   mPosition = newPosition;
 
-  NotifyOfPivotChange(oldPosition, oldStart, oldEnd);
+  NotifyOfPivotChange(oldPosition, oldStart, oldEnd,
+                      nsIAccessiblePivot::REASON_TEXT);
 
   return NS_OK;
 }
 
 // Traversal functions
 
 NS_IMETHODIMP
 nsAccessiblePivot::MoveNext(nsIAccessibleTraversalRule* aRule,
@@ -199,17 +201,17 @@ nsAccessiblePivot::MoveNext(nsIAccessibl
     return NS_ERROR_NOT_IN_TREE;
 
   nsresult rv = NS_OK;
   Accessible* accessible =
     SearchForward(anchor, aRule, (aArgc > 1) ? aIncludeStart : false, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (accessible)
-    *aResult = MovePivotInternal(accessible);
+    *aResult = MovePivotInternal(accessible, nsIAccessiblePivot::REASON_NEXT);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessiblePivot::MovePrevious(nsIAccessibleTraversalRule* aRule,
                                 nsIAccessible* aAnchor,
                                 bool aIncludeStart,
@@ -226,17 +228,17 @@ nsAccessiblePivot::MovePrevious(nsIAcces
     return NS_ERROR_NOT_IN_TREE;
 
   nsresult rv = NS_OK;
   Accessible* accessible =
     SearchBackward(anchor, aRule, (aArgc > 1) ? aIncludeStart : false, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (accessible)
-    *aResult = MovePivotInternal(accessible);
+    *aResult = MovePivotInternal(accessible, nsIAccessiblePivot::REASON_PREV);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessiblePivot::MoveFirst(nsIAccessibleTraversalRule* aRule, bool* aResult)
 {
   NS_ENSURE_ARG(aResult);
@@ -245,17 +247,17 @@ nsAccessiblePivot::MoveFirst(nsIAccessib
   if (mRoot && mRoot->IsDefunct())
     return NS_ERROR_NOT_IN_TREE;
 
   nsresult rv = NS_OK;
   Accessible* accessible = SearchForward(mRoot, aRule, true, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (accessible)
-    *aResult = MovePivotInternal(accessible);
+    *aResult = MovePivotInternal(accessible, nsIAccessiblePivot::REASON_FIRST);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessiblePivot::MoveLast(nsIAccessibleTraversalRule* aRule, bool* aResult)
 {
   NS_ENSURE_ARG(aResult);
@@ -273,17 +275,17 @@ nsAccessiblePivot::MoveLast(nsIAccessibl
   while (lastAccessible->HasChildren())
     lastAccessible = lastAccessible->LastChild();
 
   // Search backwards from last accessible and find the last occurrence in the doc
   accessible = SearchBackward(lastAccessible, aRule, true, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (accessible)
-    *aResult = MovePivotInternal(accessible);
+    *aResult = MovePivotInternal(accessible, nsAccessiblePivot::REASON_LAST);
 
   return NS_OK;
 }
 
 // TODO: Implement
 NS_IMETHODIMP
 nsAccessiblePivot::MoveNextByText(TextBoundaryType aBoundary, bool* aResult)
 {
@@ -340,17 +342,17 @@ nsAccessiblePivot::MoveToPoint(nsIAccess
           aY >= childY && aY < childY + childHeight)
         match = child;
     }
 
     child = child->Parent();
   }
 
   if (match || !aIgnoreNoMatch)
-    *aResult = MovePivotInternal(match);
+    *aResult = MovePivotInternal(match, nsIAccessiblePivot::REASON_POINT);
 
   return NS_OK;
 }
 
 // Observer functions
 
 NS_IMETHODIMP
 nsAccessiblePivot::AddObserver(nsIAccessiblePivotObserver* aObserver)
@@ -384,24 +386,25 @@ nsAccessiblePivot::IsRootDescendant(Acce
     if (accessible == mRoot)
       return true;
   } while ((accessible = accessible->Parent()));
 
   return false;
 }
 
 bool
-nsAccessiblePivot::MovePivotInternal(Accessible* aPosition)
+nsAccessiblePivot::MovePivotInternal(Accessible* aPosition,
+                                     PivotMoveReason aReason)
 {
   nsRefPtr<Accessible> oldPosition = mPosition.forget();
   mPosition = aPosition;
   PRInt32 oldStart = mStartOffset, oldEnd = mEndOffset;
   mStartOffset = mEndOffset = -1;
 
-  return NotifyOfPivotChange(oldPosition, oldStart, oldEnd);
+  return NotifyOfPivotChange(oldPosition, oldStart, oldEnd, aReason);
 }
 
 Accessible*
 nsAccessiblePivot::SearchBackward(Accessible* aAccessible,
                                   nsIAccessibleTraversalRule* aRule,
                                   bool aSearchCurrent,
                                   nsresult* aResult)
 {
@@ -514,26 +517,27 @@ nsAccessiblePivot::SearchForward(Accessi
       return accessible;
   }
 
   return nsnull;
 }
 
 bool
 nsAccessiblePivot::NotifyOfPivotChange(Accessible* aOldPosition,
-                                       PRInt32 aOldStart, PRInt32 aOldEnd)
+                                       PRInt32 aOldStart, PRInt32 aOldEnd,
+                                       PRInt16 aReason)
 {
   if (aOldPosition == mPosition &&
       aOldStart == mStartOffset && aOldEnd == mEndOffset)
     return false;
 
   nsTObserverArray<nsCOMPtr<nsIAccessiblePivotObserver> >::ForwardIterator iter(mObservers);
   while (iter.HasMore()) {
     nsIAccessiblePivotObserver* obs = iter.GetNext();
-    obs->OnPivotChanged(this, aOldPosition, aOldStart, aOldEnd);
+    obs->OnPivotChanged(this, aOldPosition, aOldStart, aOldEnd, aReason);
   }
 
   return true;
 }
 
 nsresult
 RuleCache::ApplyFilter(Accessible* aAccessible, PRUint16* aResult)
 {
--- a/accessible/src/base/nsAccessiblePivot.h
+++ b/accessible/src/base/nsAccessiblePivot.h
@@ -43,17 +43,18 @@ private:
   nsAccessiblePivot(const nsAccessiblePivot&) MOZ_DELETE;
   void operator = (const nsAccessiblePivot&) MOZ_DELETE;
 
   /*
    * Notify all observers on a pivot change. Return true if it has changed and
    * observers have been notified.
    */
   bool NotifyOfPivotChange(Accessible* aOldAccessible,
-                           PRInt32 aOldStart, PRInt32 aOldEnd);
+                           PRInt32 aOldStart, PRInt32 aOldEnd,
+                           PivotMoveReason aReason);
 
   /*
    * Check to see that the given accessible is in the pivot's subtree.
    */
   bool IsRootDescendant(Accessible* aAccessible);
 
 
   /*
@@ -70,17 +71,17 @@ private:
   Accessible* SearchBackward(Accessible* aAccessible,
                              nsIAccessibleTraversalRule* aRule,
                              bool aSearchCurrent,
                              nsresult* aResult);
 
   /*
    * Update the pivot, and notify observers. Return true if it moved.
    */
-  bool MovePivotInternal(Accessible* aPosition);
+  bool MovePivotInternal(Accessible* aPosition, PivotMoveReason aReason);
 
   /*
    * The root accessible.
    */
   nsRefPtr<Accessible> mRoot;
 
   /*
    * The current pivot position.
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -919,20 +919,22 @@ DocAccessible::Observe(nsISupports* aSub
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessiblePivotObserver
 
 NS_IMETHODIMP
 DocAccessible::OnPivotChanged(nsIAccessiblePivot* aPivot,
                               nsIAccessible* aOldAccessible,
-                              PRInt32 aOldStart, PRInt32 aOldEnd)
+                              PRInt32 aOldStart, PRInt32 aOldEnd,
+                              PivotMoveReason aReason)
 {
   nsRefPtr<AccEvent> event = new AccVCChangeEvent(this, aOldAccessible,
-                                                  aOldStart, aOldEnd);
+                                                  aOldStart, aOldEnd,
+                                                  aReason);
   nsEventShell::FireEvent(event);
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIDocumentObserver
 
--- a/accessible/src/xpcom/nsAccEvent.cpp
+++ b/accessible/src/xpcom/nsAccEvent.cpp
@@ -252,8 +252,17 @@ NS_IMETHODIMP
 nsAccVirtualCursorChangeEvent::GetOldEndOffset(PRInt32* aOldEndOffset)
 {
   NS_ENSURE_ARG_POINTER(aOldEndOffset);
 
   *aOldEndOffset =
     static_cast<AccVCChangeEvent*>(mEvent.get())->OldEndOffset();
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsAccVirtualCursorChangeEvent::GetReason(PRInt16* aReason)
+{
+  NS_ENSURE_ARG_POINTER(aReason);
+
+  *aReason = static_cast<AccVCChangeEvent*>(mEvent.get())->Reason();
+  return NS_OK;
+}
--- a/accessible/tests/mochitest/pivot.js
+++ b/accessible/tests/mochitest/pivot.js
@@ -65,31 +65,36 @@ var ObjectTraversalRule =
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 // Virtual state invokers and checkers
 
 /**
  * A checker for virtual cursor changed events.
  */
-function VCChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets)
+function VCChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets, aPivotMoveMethod)
 {
   this.__proto__ = new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc);
 
   this.check = function VCChangedChecker_check(aEvent)
   {
     SimpleTest.info("VCChangedChecker_check");
 
     var event = null;
     try {
       event = aEvent.QueryInterface(nsIAccessibleVirtualCursorChangeEvent);
     } catch (e) {
       SimpleTest.ok(false, "Does not support correct interface: " + e);
     }
 
+    SimpleTest.is(
+      event.reason,
+      VCChangedChecker.methodReasonMap[aPivotMoveMethod],
+      'wrong move reason');
+
     var position = aDocAcc.virtualCursor.position;
     var idMatches = position && position.DOMNode.id == aIdOrNameOrAcc;
     var nameMatches = position && position.name == aIdOrNameOrAcc;
     var accMatches = position == aIdOrNameOrAcc;
 
     SimpleTest.ok(idMatches || nameMatches || accMatches, "id or name matches",
                   "expecting " + aIdOrNameOrAcc + ", got '" +
                   prettyName(position));
@@ -127,16 +132,25 @@ VCChangedChecker.storePreviousPosAndOffs
 };
 
 VCChangedChecker.getPreviousPosAndOffset =
   function getPreviousPosAndOffset(aPivot)
 {
   return VCChangedChecker.prevPosAndOffset[aPivot];
 };
 
+VCChangedChecker.methodReasonMap = {
+  'moveNext': nsIAccessiblePivot.REASON_NEXT,
+  'movePrevious': nsIAccessiblePivot.REASON_PREV,
+  'moveFirst': nsIAccessiblePivot.REASON_FIRST,
+  'moveLast': nsIAccessiblePivot.REASON_LAST,
+  'setTextRange': nsIAccessiblePivot.REASON_TEXT,
+  'moveToPoint': nsIAccessiblePivot.REASON_POINT
+};
+
 /**
  * Set a text range in the pivot and wait for virtual cursor change event.
  *
  * @param aDocAcc         [in] document that manages the virtual cursor
  * @param aTextAccessible [in] accessible to set to virtual cursor's position
  * @param aTextOffsets    [in] start and end offsets of text range to set in
  *                        virtual cursor.
  */
@@ -154,17 +168,17 @@ function setVCRangeInvoker(aDocAcc, aTex
 
   this.getID = function setVCRangeInvoker_getID()
   {
     return "Set offset in " + prettyName(aTextAccessible) +
       " to (" + aTextOffsets[0] + ", " + aTextOffsets[1] + ")";
   };
 
   this.eventSeq = [
-    new VCChangedChecker(aDocAcc, aTextAccessible, aTextOffsets)
+    new VCChangedChecker(aDocAcc, aTextAccessible, aTextOffsets, "setTextRange")
   ];
 }
 
 /**
  * Move the pivot and wait for virtual cursor change event.
  *
  * @param aDocAcc          [in] document that manages the virtual cursor
  * @param aPivotMoveMethod [in] method to test (ie. "moveNext", "moveFirst", etc.)
@@ -186,17 +200,19 @@ function setVCPosInvoker(aDocAcc, aPivot
   };
 
   this.getID = function setVCPosInvoker_getID()
   {
     return "Do " + (expectMove ? "" : "no-op ") + aPivotMoveMethod;
   };
 
   if (expectMove) {
-    this.eventSeq = [ new VCChangedChecker(aDocAcc, aIdOrNameOrAcc) ];
+    this.eventSeq = [
+      new VCChangedChecker(aDocAcc, aIdOrNameOrAcc, null, aPivotMoveMethod)
+    ];
   } else {
     this.eventSeq = [];
     this.unexpectedEventSeq = [
       new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc)
     ];
   }
 }
 
@@ -228,17 +244,19 @@ function moveVCCoordInvoker(aDocAcc, aX,
   };
 
   this.getID = function setVCPosInvoker_getID()
   {
     return "Do " + (expectMove ? "" : "no-op ") + "moveToPoint " + aIdOrNameOrAcc;
   };
 
   if (expectMove) {
-    this.eventSeq = [ new VCChangedChecker(aDocAcc, aIdOrNameOrAcc) ];
+    this.eventSeq = [
+      new VCChangedChecker(aDocAcc, aIdOrNameOrAcc, null, 'moveToPoint')
+    ];
   } else {
     this.eventSeq = [];
     this.unexpectedEventSeq = [
       new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc)
     ];
   }
 }