зеркало из https://github.com/mozilla/gecko-dev.git
386 строки
9.5 KiB
JavaScript
386 строки
9.5 KiB
JavaScript
/* import-globals-from common.js */
|
|
|
|
/**
|
|
* Tests if the given child and grand child accessibles at the given point are
|
|
* expected.
|
|
*
|
|
* @param aID [in] accessible identifier
|
|
* @param aX [in] x coordinate of the point relative accessible
|
|
* @param aY [in] y coordinate of the point relative accessible
|
|
* @param aChildID [in] expected child accessible
|
|
* @param aGrandChildID [in] expected child accessible
|
|
*/
|
|
function testChildAtPoint(aID, aX, aY, aChildID, aGrandChildID) {
|
|
var child = getChildAtPoint(aID, aX, aY, false);
|
|
var expectedChild = getAccessible(aChildID);
|
|
|
|
var msg =
|
|
"Wrong direct child accessible at the point (" +
|
|
aX +
|
|
", " +
|
|
aY +
|
|
") of " +
|
|
prettyName(aID);
|
|
isObject(child, expectedChild, msg);
|
|
|
|
var grandChild = getChildAtPoint(aID, aX, aY, true);
|
|
var expectedGrandChild = getAccessible(aGrandChildID);
|
|
|
|
msg =
|
|
"Wrong deepest child accessible at the point (" +
|
|
aX +
|
|
", " +
|
|
aY +
|
|
") of " +
|
|
prettyName(aID);
|
|
isObject(grandChild, expectedGrandChild, msg);
|
|
}
|
|
|
|
/**
|
|
* Test if getChildAtPoint returns the given child and grand child accessibles
|
|
* at coordinates of child accessible (direct and deep hit test).
|
|
*/
|
|
function hitTest(aContainerID, aChildID, aGrandChildID) {
|
|
var container = getAccessible(aContainerID);
|
|
var child = getAccessible(aChildID);
|
|
var grandChild = getAccessible(aGrandChildID);
|
|
|
|
var [x, y] = getBoundsForDOMElm(child);
|
|
|
|
var actualChild = container.getChildAtPoint(x + 1, y + 1);
|
|
isObject(
|
|
actualChild,
|
|
child,
|
|
"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) {
|
|
SpecialPowers.setFullZoom(aDocument.defaultView, aZoom);
|
|
}
|
|
|
|
/**
|
|
* Set the relative resolution of this document. This is what apz does.
|
|
* On non-mobile platforms you won't see a visible change.
|
|
*/
|
|
function setResolution(aDocument, aZoom) {
|
|
var windowUtils = aDocument.defaultView.windowUtils;
|
|
|
|
windowUtils.setResolutionAndScaleTo(aZoom);
|
|
}
|
|
|
|
/**
|
|
* Return child accessible at the given point.
|
|
*
|
|
* @param aIdentifier [in] accessible identifier
|
|
* @param aX [in] x coordinate of the point relative accessible
|
|
* @param aY [in] y coordinate of the point relative accessible
|
|
* @param aFindDeepestChild [in] points whether deepest or nearest child should
|
|
* be returned
|
|
* @return the child accessible at the given point
|
|
*/
|
|
function getChildAtPoint(aIdentifier, aX, aY, aFindDeepestChild) {
|
|
var acc = getAccessible(aIdentifier);
|
|
if (!acc) {
|
|
return null;
|
|
}
|
|
|
|
var [screenX, screenY] = getBoundsForDOMElm(acc.DOMNode);
|
|
|
|
var x = screenX + aX;
|
|
var y = screenY + aY;
|
|
|
|
try {
|
|
if (aFindDeepestChild) {
|
|
return acc.getDeepestChildAtPoint(x, y);
|
|
}
|
|
return acc.getChildAtPoint(x, y);
|
|
} catch (e) {}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Test the accessible position.
|
|
*/
|
|
function testPos(aID, aPoint) {
|
|
var [expectedX, expectedY] =
|
|
aPoint != undefined ? aPoint : getBoundsForDOMElm(aID);
|
|
|
|
var [x, y] = getBounds(aID);
|
|
is(x, expectedX, "Wrong x coordinate of " + prettyName(aID));
|
|
is(y, expectedY, "Wrong y coordinate of " + prettyName(aID));
|
|
}
|
|
|
|
/**
|
|
* Test the accessible boundaries.
|
|
*/
|
|
function testBounds(aID, aRect) {
|
|
var [expectedX, expectedY, expectedWidth, expectedHeight] =
|
|
aRect != undefined ? aRect : getBoundsForDOMElm(aID);
|
|
|
|
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]);
|
|
hyperText.getRangeExtents(
|
|
aStartOffset,
|
|
aEndOffset,
|
|
xObj,
|
|
yObj,
|
|
widthObj,
|
|
heightObj,
|
|
aCoordOrigin
|
|
);
|
|
|
|
// x
|
|
is(
|
|
xObj.value,
|
|
expectedX,
|
|
"Wrong x coordinate of text between offsets (" +
|
|
aStartOffset +
|
|
", " +
|
|
aEndOffset +
|
|
") for " +
|
|
prettyName(aID)
|
|
);
|
|
|
|
// y
|
|
isWithin(
|
|
yObj.value,
|
|
expectedY,
|
|
1,
|
|
`y coord of text between offsets (${aStartOffset}, ${aEndOffset}) ` +
|
|
`for ${prettyName(aID)}`
|
|
);
|
|
|
|
// Width
|
|
var msg =
|
|
"Wrong width of text between offsets (" +
|
|
aStartOffset +
|
|
", " +
|
|
aEndOffset +
|
|
") for " +
|
|
prettyName(aID);
|
|
if (widthObj.value == expectedWidth) {
|
|
ok(true, msg);
|
|
} else {
|
|
todo(false, msg);
|
|
} // fails on some windows machines
|
|
|
|
// Height
|
|
isWithin(
|
|
heightObj.value,
|
|
expectedHeight,
|
|
1,
|
|
`height of text between offsets (${aStartOffset}, ${aEndOffset}) ` +
|
|
`for ${prettyName(aID)}`
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Return the accessible coordinates relative to the screen in device pixels.
|
|
*/
|
|
function getPos(aID) {
|
|
var accessible = getAccessible(aID);
|
|
var x = {},
|
|
y = {};
|
|
accessible.getBounds(x, y, {}, {});
|
|
return [x.value, y.value];
|
|
}
|
|
|
|
/**
|
|
* Return the accessible coordinates and size relative to the screen in device
|
|
* pixels. This methods also retrieves coordinates in CSS pixels and ensures that they
|
|
* match Dev pixels with a given device pixel ratio.
|
|
*/
|
|
function getBounds(aID, aDPR = window.devicePixelRatio) {
|
|
const accessible = getAccessible(aID);
|
|
let x = {},
|
|
y = {},
|
|
width = {},
|
|
height = {};
|
|
let xInCSS = {},
|
|
yInCSS = {},
|
|
widthInCSS = {},
|
|
heightInCSS = {};
|
|
accessible.getBounds(x, y, width, height);
|
|
accessible.getBoundsInCSSPixels(xInCSS, yInCSS, widthInCSS, heightInCSS);
|
|
|
|
isWithin(
|
|
x.value / aDPR,
|
|
xInCSS.value,
|
|
1,
|
|
"Heights in CSS pixels is calculated correctly"
|
|
);
|
|
isWithin(
|
|
y.value / aDPR,
|
|
yInCSS.value,
|
|
1,
|
|
"Heights in CSS pixels is calculated correctly"
|
|
);
|
|
isWithin(
|
|
width.value / aDPR,
|
|
widthInCSS.value,
|
|
1,
|
|
"Heights in CSS pixels is calculated correctly"
|
|
);
|
|
isWithin(
|
|
height.value / aDPR,
|
|
heightInCSS.value,
|
|
1,
|
|
"Heights in CSS pixels is calculated correctly"
|
|
);
|
|
|
|
return [x.value, y.value, width.value, height.value];
|
|
}
|
|
|
|
function getRangeExtents(aID, aStartOffset, aEndOffset, aCoordOrigin) {
|
|
var hyperText = getAccessible(aID, [nsIAccessibleText]);
|
|
var x = {},
|
|
y = {},
|
|
width = {},
|
|
height = {};
|
|
hyperText.getRangeExtents(
|
|
aStartOffset,
|
|
aEndOffset,
|
|
x,
|
|
y,
|
|
width,
|
|
height,
|
|
aCoordOrigin
|
|
);
|
|
return [x.value, y.value, width.value, height.value];
|
|
}
|
|
|
|
/**
|
|
* Return DOM node coordinates relative the screen and its size in device
|
|
* pixels.
|
|
*/
|
|
function getBoundsForDOMElm(aID) {
|
|
var x = 0,
|
|
y = 0,
|
|
width = 0,
|
|
height = 0;
|
|
|
|
var elm = getNode(aID);
|
|
if (elm.localName == "area") {
|
|
var mapName = elm.parentNode.getAttribute("name");
|
|
var selector = "[usemap='#" + mapName + "']";
|
|
var img = elm.ownerDocument.querySelector(selector);
|
|
|
|
var areaCoords = elm.coords.split(",");
|
|
var areaX = parseInt(areaCoords[0]);
|
|
var areaY = parseInt(areaCoords[1]);
|
|
var areaWidth = parseInt(areaCoords[2]) - areaX;
|
|
var areaHeight = parseInt(areaCoords[3]) - areaY;
|
|
|
|
let rect = img.getBoundingClientRect();
|
|
x = rect.left + areaX;
|
|
y = rect.top + areaY;
|
|
width = areaWidth;
|
|
height = areaHeight;
|
|
} else {
|
|
let rect = elm.getBoundingClientRect();
|
|
x = rect.left;
|
|
y = rect.top;
|
|
width = rect.width;
|
|
height = rect.height;
|
|
}
|
|
|
|
var elmWindow = elm.ownerGlobal;
|
|
return CSSToDevicePixels(
|
|
elmWindow,
|
|
x + elmWindow.mozInnerScreenX,
|
|
y + elmWindow.mozInnerScreenY,
|
|
width,
|
|
height
|
|
);
|
|
}
|
|
|
|
function CSSToDevicePixels(aWindow, aX, aY, aWidth, aHeight) {
|
|
var winUtil = aWindow.windowUtils;
|
|
|
|
var ratio = winUtil.screenPixelsPerCSSPixel;
|
|
|
|
// CSS pixels and ratio can be not integer. Device pixels are always integer.
|
|
// Do our best and hope it works.
|
|
return [
|
|
Math.round(aX * ratio),
|
|
Math.round(aY * ratio),
|
|
Math.round(aWidth * ratio),
|
|
Math.round(aHeight * ratio),
|
|
];
|
|
}
|