Bug 727942 - scrollSubstringToPoint is broken when page is zoomed, r=tbsaunde
authorAlexander Surkov <surkov.alexander@gmail.com>
Sun, 21 Oct 2012 10:38:15 +0900
changeset 111123 6a24636cd4a2751dd04ed7e7d314184885406e00
parent 111122 0e73daa7fc4cd2634f22021d39b0dddb575829b7
child 111124 585b254104f26e53fb752157b31b1813702c08c2
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewerstbsaunde
bugs727942
milestone19.0a1
Bug 727942 - scrollSubstringToPoint is broken when page is zoomed, r=tbsaunde
accessible/src/generic/HyperTextAccessible.cpp
accessible/tests/mochitest/layout.js
accessible/tests/mochitest/scroll/Makefile.in
accessible/tests/mochitest/scroll/test_zoom_text.html
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -1893,41 +1893,40 @@ HyperTextAccessible::ScrollSubstringToPo
   nsresult rv = nsAccUtils::ConvertToScreenCoords(aX, aY, aCoordinateType,
                                                   this, &coords);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<nsRange> range = new nsRange();
   rv = HypertextOffsetsToDOMRange(aStartIndex, aEndIndex, range);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsPresContext *presContext = frame->PresContext();
+  nsPresContext* presContext = frame->PresContext();
+  nsPoint coordsInAppUnits =
+    coords.ToAppUnits(presContext->AppUnitsPerDevPixel());
 
   bool initialScrolled = false;
   nsIFrame *parentFrame = frame;
   while ((parentFrame = parentFrame->GetParent())) {
     nsIScrollableFrame *scrollableFrame = do_QueryFrame(parentFrame);
     if (scrollableFrame) {
       if (!initialScrolled) {
         // Scroll substring to the given point. Turn the point into percents
         // relative scrollable area to use nsCoreUtils::ScrollSubstringTo.
-        nsIntRect frameRect = parentFrame->GetScreenRectExternal();
-        int32_t devOffsetX = coords.x - frameRect.x;
-        int32_t devOffsetY = coords.y - frameRect.y;
-
-        nsPoint offsetPoint(presContext->DevPixelsToAppUnits(devOffsetX),
-                            presContext->DevPixelsToAppUnits(devOffsetY));
+        nsRect frameRect = parentFrame->GetScreenRectInAppUnits();
+        nscoord offsetPointX = coordsInAppUnits.x - frameRect.x;
+        nscoord offsetPointY = coordsInAppUnits.y - frameRect.y;
 
         nsSize size(parentFrame->GetSize());
 
         // avoid divide by zero
         size.width = size.width ? size.width : 1;
         size.height = size.height ? size.height : 1;
 
-        int16_t hPercent = offsetPoint.x * 100 / size.width;
-        int16_t vPercent = offsetPoint.y * 100 / size.height;
+        int16_t hPercent = offsetPointX * 100 / size.width;
+        int16_t vPercent = offsetPointY * 100 / size.height;
 
         rv = nsCoreUtils::ScrollSubstringTo(frame, range, vPercent, hPercent);
         NS_ENSURE_SUCCESS(rv, rv);
 
         initialScrolled = true;
       } else {
         // Substring was scrolled to the given point already inside its closest
         // scrollable area. If there are nested scrollable areas then make
--- a/accessible/tests/mochitest/layout.js
+++ b/accessible/tests/mochitest/layout.js
@@ -127,16 +127,34 @@ function testBounds(aID, aRect)
   var [x, y, width, height] = getBounds(aID);
   is(x, expectedX, "Wrong x coordinate of " + prettyName(aID));
   is(y, expectedY, "Wrong y coordinate of " + prettyName(aID));
   is(width, expectedWidth, "Wrong width of " + prettyName(aID));
   is(height, expectedHeight, "Wrong height of " + prettyName(aID));
 }
 
 /**
+ * Test text position at the given offset.
+ */
+function testTextPos(aID, aOffset, aPoint, aCoordOrigin)
+{
+  var [expectedX, expectedY] = aPoint;
+
+  var xObj = {}, yObj = {};
+  var hyperText = getAccessible(aID, [nsIAccessibleText]);
+  hyperText.getCharacterExtents(aOffset, xObj, yObj, {}, {}, aCoordOrigin);
+  is(xObj.value, expectedX,
+     "Wrong x coordinate at offset " + aOffset + " for " + prettyName(aID));
+  ok(yObj.value - expectedY < 2 && expectedY - yObj.value < 2,
+     "Wrong y coordinate at offset " + aOffset + " for " + prettyName(aID) +
+     " - got " + yObj.value + ", expected " + expectedY +
+     "The difference doesn't exceed 1.");
+}
+
+/**
  * Test text bounds that is enclosed betwene the given offsets.
  */
 function testTextBounds(aID, aStartOffset, aEndOffset, aRect, aCoordOrigin)
 {
   var [expectedX, expectedY, expectedWidth, expectedHeight] = aRect;
 
   var xObj = {}, yObj = {}, widthObj = {}, heightObj = {};
   var hyperText = getAccessible(aID, [nsIAccessibleText]);
--- a/accessible/tests/mochitest/scroll/Makefile.in
+++ b/accessible/tests/mochitest/scroll/Makefile.in
@@ -7,12 +7,13 @@ DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible/scroll
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_A11Y_FILES =\
+		test_zoom_text.html \
 		test_zoom.html \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/scroll/test_zoom_text.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Test scrollSubstringToPoint when page is zoomed</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../layout.js"></script>
+  <script type="application/javascript"
+          src="../browser.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var tabDocument = currentTabDocument();
+      var paragraphNode = tabDocument.getElementById("paragraph");
+      var paragraph = getAccessible(paragraphNode, [nsIAccessibleText]);
+      var offset = 64; // beginning of 4th stanza
+
+      var [x, y] = getPos(paragraph);
+      var [docX, docY] = getPos(tabDocument);
+
+      paragraph.scrollSubstringToPoint(offset, offset,
+                                       COORDTYPE_SCREEN_RELATIVE, docX, docY);
+      testTextPos(paragraph, offset, [x, docY], COORDTYPE_SCREEN_RELATIVE);
+
+      zoomDocument(tabDocument, 2.0);
+
+      paragraphNode = tabDocument.getElementById("paragraph2");
+      paragraph = getAccessible(paragraphNode, [nsIAccessibleText]);
+      offset = 52; // // beginning of 4th stanza
+      var [x, y] = getPos(paragraph);
+      paragraph.scrollSubstringToPoint(offset, offset,
+                                       COORDTYPE_SCREEN_RELATIVE, docX, docY);
+      testTextPos(paragraph, offset, [x, docY], COORDTYPE_SCREEN_RELATIVE);
+
+      closeBrowserWindow();
+      SimpleTest.finish();
+    }
+
+    var url = "data:text/html,<html>" +
+      "<meta http-equiv='Content-Type' content='text/html;charset=utf-8' />" +
+      "<body>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br><hr>" +
+      "<p id='paragraph'>" +
+      "  Пошел котик на торжок<br>" +
+      "  Купил котик пирожок<br>" +
+      "  Пошел котик на улочку<br>" +
+      "  Купил котик булочку<br>" +
+      "</p>" +
+      "<hr><br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br><hr>" +
+      "<p id='paragraph2'>" +
+      "  Самому ли съесть<br>" +
+      "  Либо Сашеньке снесть<br>" +
+      "  Я и сам укушу<br>" +
+      "  Я и Сашеньке снесу<br>" +
+      "</p>" +
+      "<hr><br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "<br><br><br><br><br><br><br><br><br><br>" +
+      "</body></html>";
+
+    SimpleTest.waitForExplicitFinish();
+    openBrowserWindow(doTest,
+                      url,
+                      { left: 0, top: 0, width: 600, height: 600 });
+  </script>
+
+</head>
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=727942"
+     title="scrollSubstringToPoint is broken when page is zoomed">
+    Mozilla Bug 727942
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+</body>
+</html>