Bug 727942 - getOffsetAtPoint returns incorrect value when page is zoomed, r=tbsaunde
authorAlexander Surkov <surkov.alexander@gmail.com>
Sat, 20 Oct 2012 18:03:48 +0900
changeset 110998 a48b0c4084badbf5a3973c833466ddbc81e4bea3
parent 110997 b097b04096f7586bf5647bf309b0620a497a34fa
child 110999 af2ae674602435e98825f5d939eb87784668dc94
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewerstbsaunde
bugs727942
milestone19.0a1
Bug 727942 - getOffsetAtPoint returns incorrect value when page is zoomed, r=tbsaunde
accessible/src/generic/HyperTextAccessible.cpp
accessible/tests/mochitest/hittest/Makefile.in
accessible/tests/mochitest/hittest/test_zoom_text.html
accessible/tests/mochitest/layout.js
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -1229,33 +1229,32 @@ HyperTextAccessible::GetOffsetAtPoint(in
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsIFrame *hyperFrame = GetFrame();
   if (!hyperFrame) {
     return NS_ERROR_FAILURE;
   }
-  nsIntRect frameScreenRect = hyperFrame->GetScreenRectExternal();
 
   nsIntPoint coords;
   nsresult rv = nsAccUtils::ConvertToScreenCoords(aX, aY, aCoordType,
                                                   this, &coords);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // coords are currently screen coordinates, and we need to turn them into
-  // frame coordinates relative to the current accessible
-  if (!frameScreenRect.Contains(coords.x, coords.y)) {
+  nsPresContext* presContext = mDoc->PresContext();
+  nsPoint coordsInAppUnits =
+    coords.ToAppUnits(presContext->AppUnitsPerDevPixel());
+
+  nsRect frameScreenRect = hyperFrame->GetScreenRectInAppUnits();
+  if (!frameScreenRect.Contains(coordsInAppUnits.x, coordsInAppUnits.y))
     return NS_OK;   // Not found, will return -1
-  }
-  nsIntPoint pxInHyperText(coords.x - frameScreenRect.x,
-                           coords.y - frameScreenRect.y);
-  nsPresContext* context = mDoc->PresContext();
-  nsPoint pointInHyperText(context->DevPixelsToAppUnits(pxInHyperText.x),
-                           context->DevPixelsToAppUnits(pxInHyperText.y));
+
+  nsPoint pointInHyperText(coordsInAppUnits.x - frameScreenRect.x,
+                           coordsInAppUnits.y - frameScreenRect.y);
 
   // Go through the frames to check if each one has the point.
   // When one does, add up the character offsets until we have a match
 
   // We have an point in an accessible child of this, now we need to add up the
   // offsets before it to what we already have
   int32_t offset = 0;
   uint32_t childCount = ChildCount();
@@ -1264,17 +1263,17 @@ HyperTextAccessible::GetOffsetAtPoint(in
 
     nsIFrame *primaryFrame = childAcc->GetFrame();
     NS_ENSURE_TRUE(primaryFrame, NS_ERROR_FAILURE);
 
     nsIFrame *frame = primaryFrame;
     while (frame) {
       nsIContent *content = frame->GetContent();
       NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
-      nsPoint pointInFrame = pointInHyperText - frame->GetOffsetToExternal(hyperFrame);
+      nsPoint pointInFrame = pointInHyperText - frame->GetOffsetTo(hyperFrame);
       nsSize frameSize = frame->GetSize();
       if (pointInFrame.x < frameSize.width && pointInFrame.y < frameSize.height) {
         // Finished
         if (frame->GetType() == nsGkAtoms::textFrame) {
           nsIFrame::ContentOffsets contentOffsets =
             frame->GetContentOffsetsFromPointExternal(pointInFrame, nsIFrame::IGNORE_SELECTION_STYLE);
           if (contentOffsets.IsNull() || contentOffsets.content != content) {
             return NS_OK; // Not found, will return -1
--- a/accessible/tests/mochitest/hittest/Makefile.in
+++ b/accessible/tests/mochitest/hittest/Makefile.in
@@ -9,14 +9,15 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible/hittest
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_A11Y_FILES = \
 		test_browser.html \
 		test_general.html \
+		test_zoom_text.html \
 		test_zoom_tree.xul \
 		test_zoom.html \
 		zoom_tree.xul \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/hittest/test_zoom_text.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>getOffsetAtPoint 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="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../layout.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      var hyperText = getNode("paragraph");
+      var textNode = hyperText.firstChild;
+      var [x, y, width, height] = getBounds(textNode);
+      testOffsetAtPoint(hyperText, x + width / 2, y + height / 2,
+                        COORDTYPE_SCREEN_RELATIVE,
+                        hyperText.textContent.length / 2);
+
+      zoomDocument(document, 2.0);
+
+      var [x, y, width, height] = getBounds(textNode);
+      testOffsetAtPoint(hyperText, x + width / 2, y + height / 2,
+                        COORDTYPE_SCREEN_RELATIVE,
+                        hyperText.textContent.length / 2);
+
+      zoomDocument(document, 1.0);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=727942"
+     title="getOffsetAtPoint returns incorrect value when page is zoomed">
+    Mozilla Bug 727942
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+  <p id="paragraph" style="font-family: monospace;">Болтали две сороки</p>
+</body>
+</html>
--- a/accessible/tests/mochitest/layout.js
+++ b/accessible/tests/mochitest/layout.js
@@ -42,16 +42,28 @@ function hitTest(aContainerID, aChildID,
            "Wrong direct child of " + prettyName(aContainerID));
 
   var actualGrandChild = container.getDeepestChildAtPoint(x + 1, y + 1);
   isObject(actualGrandChild, grandChild,
            "Wrong deepest child of " + prettyName(aContainerID));
 }
 
 /**
+ * Test if getOffsetAtPoint returns the given text offset at given coordinates.
+ */
+function testOffsetAtPoint(aHyperTextID, aX, aY, aCoordType, aExpectedOffset)
+{
+  var hyperText = getAccessible(aHyperTextID, [nsIAccessibleText]);
+  var offset = hyperText.getOffsetAtPoint(aX, aY, aCoordType);
+  is(offset, aExpectedOffset,
+     "Wrong offset at given point (" + aX + ", " + aY + ") for " +
+     prettyName(aHyperTextID));
+}
+
+/**
  * Zoom the given document.
  */
 function zoomDocument(aDocument, aZoom)
 {
   var docShell = aDocument.defaultView.
     QueryInterface(Components.interfaces.nsIInterfaceRequestor).
     getInterface(Components.interfaces.nsIWebNavigation).
     QueryInterface(Components.interfaces.nsIDocShell);