Bug 935254 - getTextAt broken for list items. r=tbsaunde, a=lsblakk
authorAlexander Surkov <surkov.alexander@gmail.com>
Tue, 10 Dec 2013 07:40:54 -0500
changeset 175306 453a325316439a3136e3d10b4e61e451d7e4f9de
parent 175305 a77b28e73f60b87adc260557d335ee53c0f73df3
child 175307 10450b2660bcdd791d01d8c97803525fe3e92baf
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde, lsblakk
bugs935254
milestone28.0a2
Bug 935254 - getTextAt broken for list items. r=tbsaunde, a=lsblakk
accessible/src/generic/HyperTextAccessible.cpp
accessible/src/generic/HyperTextAccessible.h
accessible/src/html/HTMLListAccessible.cpp
accessible/src/html/HTMLListAccessible.h
accessible/tests/mochitest/common.js
accessible/tests/mochitest/text/test_lineboundary.html
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -653,40 +653,25 @@ HyperTextAccessible::FindOffset(int32_t 
     frameAtOffset->PeekOffset(&pos);
   }
   if (!pos.mResultContent)
     return -1;
 
   // Turn the resulting node and offset into a hyperTextOffset
   // If finalAccessible is nullptr, then DOMPointToHypertextOffset() searched
   // through the hypertext children without finding the node/offset position.
-  int32_t hyperTextOffset;
+  int32_t hyperTextOffset = 0;
   Accessible* finalAccessible =
     DOMPointToHypertextOffset(pos.mResultContent, pos.mContentOffset,
                               &hyperTextOffset, aDirection == eDirNext);
 
-  if (!finalAccessible && aDirection == eDirPrevious) {
-    // If we reached the end during search, this means we didn't find the DOM point
-    // and we're actually at the start of the paragraph
-    hyperTextOffset = 0;
-  }  
-  else if (aAmount == eSelectBeginLine) {
-    Accessible* firstChild = mChildren.SafeElementAt(0, nullptr);
-    // For line selection with needsStart, set start of line exactly to line break
-    if (pos.mContentOffset == 0 && firstChild &&
-        firstChild->Role() == roles::STATICTEXT &&
-        static_cast<int32_t>(nsAccUtils::TextLength(firstChild)) == hyperTextOffset) {
-      // XXX Bullet hack -- we should remove this once list bullets use anonymous content
-      hyperTextOffset = 0;
-    }
-    if (aWordMovementType != eStartWord && aAmount != eSelectBeginLine &&
-        hyperTextOffset > 0) {
-      -- hyperTextOffset;
-    }
-  }
+  // If we reached the end during search, this means we didn't find the DOM point
+  // and we're actually at the start of the paragraph
+  if (!finalAccessible && aDirection == eDirPrevious)
+    return 0;
 
   return hyperTextOffset;
 }
 
 int32_t
 HyperTextAccessible::FindLineBoundary(int32_t aOffset,
                                       EWhichLineBoundary aWhichLineBoundary)
 {
--- a/accessible/src/generic/HyperTextAccessible.h
+++ b/accessible/src/generic/HyperTextAccessible.h
@@ -427,19 +427,19 @@ protected:
    */
   int32_t FindLineBoundary(int32_t aOffset,
                            EWhichLineBoundary aWhichLineBoundary);
 
   /**
    * Return an offset corresponding to the given direction and selection amount
    * relative the given offset. A helper used to find word or line boundaries.
    */
-  int32_t FindOffset(int32_t aOffset, nsDirection aDirection,
-                     nsSelectionAmount aAmount,
-                     EWordMovementType aWordMovementType = eDefaultBehavior);
+  virtual int32_t FindOffset(int32_t aOffset, nsDirection aDirection,
+                             nsSelectionAmount aAmount,
+                             EWordMovementType aWordMovementType = eDefaultBehavior);
 
   /**
     * Provides information for substring that is defined by the given start
     * and end offsets for this hyper text.
     *
     * @param  aStartOffset  [inout] the start offset into the hyper text. This
     *                       is also an out parameter used to return the offset
     *                       into the start frame's rendered text content
--- a/accessible/src/html/HTMLListAccessible.cpp
+++ b/accessible/src/html/HTMLListAccessible.cpp
@@ -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 "HTMLListAccessible.h"
 
 #include "DocAccessible.h"
+#include "nsAccUtils.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsBlockFrame.h"
 #include "nsBulletFrame.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
@@ -92,16 +93,43 @@ HTMLLIAccessible::GetBounds(int32_t* aX,
   rv = mBullet->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *aWidth += *aX - bulletX;
   *aX = bulletX; // Move x coordinate of list item over to cover bullet as well
   return NS_OK;
 }
 
+int32_t
+HTMLLIAccessible::FindOffset(int32_t aOffset, nsDirection aDirection,
+                             nsSelectionAmount aAmount,
+                             EWordMovementType aWordMovementType)
+{
+  Accessible* child = GetChildAtOffset(aOffset);
+  if (!child)
+    return -1;
+
+  if (child != mBullet) {
+    if (aDirection == eDirPrevious &&
+        (aAmount == eSelectBeginLine || aAmount == eSelectLine))
+      return 0;
+
+    return HyperTextAccessible::FindOffset(aOffset, aDirection,
+                                           aAmount, aWordMovementType);
+  }
+
+  if (aDirection == eDirPrevious)
+    return 0;
+
+  if (aAmount == eSelectEndLine || aAmount == eSelectLine)
+    return CharacterCount();
+
+  return nsAccUtils::TextLength(child);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLLIAccessible: public
 
 void
 HTMLLIAccessible::UpdateBullet(bool aHasBullet)
 {
   if (aHasBullet == !!mBullet) {
     NS_NOTREACHED("Bullet and accessible are in sync already!");
--- a/accessible/src/html/HTMLListAccessible.h
+++ b/accessible/src/html/HTMLListAccessible.h
@@ -50,17 +50,22 @@ public:
   NS_IMETHOD GetBounds(int32_t* aX, int32_t* aY,
                        int32_t* aWidth, int32_t* aHeight);
 
   // Accessible
   virtual void Shutdown();
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
 
-  // nsHTMLLIAccessible
+  // HyperTextAccessible
+  virtual int32_t FindOffset(int32_t aOffset, nsDirection aDirection,
+                             nsSelectionAmount aAmount,
+                             EWordMovementType aWordMovementType) MOZ_OVERRIDE;
+
+  // HTMLLIAccessible
   void UpdateBullet(bool aHasBullet);
 
 protected:
   // Accessible
   virtual void CacheChildren();
 
 private:
   nsRefPtr<HTMLListBulletAccessible> mBullet;
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -74,17 +74,18 @@ const STATE_BUSY = nsIAccessibleStates.S
 const SCROLL_TYPE_ANYWHERE = nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE;
 
 const COORDTYPE_SCREEN_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_SCREEN_RELATIVE;
 const COORDTYPE_WINDOW_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_WINDOW_RELATIVE;
 const COORDTYPE_PARENT_RELATIVE = nsIAccessibleCoordinateType.COORDTYPE_PARENT_RELATIVE;
 
 const kEmbedChar = String.fromCharCode(0xfffc);
 
-const kDiscBulletText = String.fromCharCode(0x2022) + " ";
+const kDiscBulletChar = String.fromCharCode(0x2022);
+const kDiscBulletText = kDiscBulletChar + " ";
 const kCircleBulletText = String.fromCharCode(0x25e6) + " ";
 const kSquareBulletText = String.fromCharCode(0x25aa) + " ";
 
 const MAX_TRIM_LENGTH = 100;
 
 /**
  * nsIAccessibleRetrieval service.
  */
--- a/accessible/tests/mochitest/text/test_lineboundary.html
+++ b/accessible/tests/mochitest/text/test_lineboundary.html
@@ -103,16 +103,22 @@
 
       testTextAtOffset([ getAccessible("ht_2").firstChild.firstChild ],
                        BOUNDARY_LINE_START,
                        [ [ 0, 3, "foo", 0, 3 ] ]);
       testTextAtOffset([ getAccessible("ht_3").firstChild.firstChild ],
                        BOUNDARY_LINE_START,
                        [ [ 0, 3, "foo\n", 0, 4 ], [ 4, 4, "", 4, 4 ] ]);
 
+      //////////////////////////////////////////////////////////////////////////
+      // list items
+
+      testTextAtOffset([ "li1" ], BOUNDARY_LINE_START,
+                       [ [ 0, 5, kDiscBulletChar + "Item", 0, 5 ] ]);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
@@ -161,10 +167,14 @@ two words
 two words
 </textarea>
   </pre>
 
   <iframe id="ht_1" src="data:text/html,<html><body>a <a href=''>b</a> c</body></html>"></iframe>
 
   <iframe id="ht_2" src="data:text/html,<div contentEditable='true'>foo<br/></div>"></iframe>
   <iframe id="ht_3" src="data:text/html,<div contentEditable='true'>foo<br/><br/></div>"></iframe>
+
+  <ul>
+    <li id="li1">Item</li>
+  </ul>
 </body>
 </html>