|
1 /** |
|
2 * Tests if the given child and grand child accessibles at the given point are |
|
3 * expected. |
|
4 * |
|
5 * @param aID [in] accessible identifier |
|
6 * @param aX [in] x coordinate of the point relative accessible |
|
7 * @param aY [in] y coordinate of the point relative accessible |
|
8 * @param aChildID [in] expected child accessible |
|
9 * @param aGrandChildID [in] expected child accessible |
|
10 */ |
|
11 function testChildAtPoint(aID, aX, aY, aChildID, aGrandChildID) |
|
12 { |
|
13 var child = getChildAtPoint(aID, aX, aY, false); |
|
14 var expectedChild = getAccessible(aChildID); |
|
15 |
|
16 var msg = "Wrong direct child accessible at the point (" + aX + ", " + aY + |
|
17 ") of " + prettyName(aID); |
|
18 isObject(child, expectedChild, msg); |
|
19 |
|
20 var grandChild = getChildAtPoint(aID, aX, aY, true); |
|
21 var expectedGrandChild = getAccessible(aGrandChildID); |
|
22 |
|
23 msg = "Wrong deepest child accessible at the point (" + aX + ", " + aY + |
|
24 ") of " + prettyName(aID); |
|
25 isObject(grandChild, expectedGrandChild, msg); |
|
26 } |
|
27 |
|
28 /** |
|
29 * Test if getChildAtPoint returns the given child and grand child accessibles |
|
30 * at coordinates of child accessible (direct and deep hit test). |
|
31 */ |
|
32 function hitTest(aContainerID, aChildID, aGrandChildID) |
|
33 { |
|
34 var container = getAccessible(aContainerID); |
|
35 var child = getAccessible(aChildID); |
|
36 var grandChild = getAccessible(aGrandChildID); |
|
37 |
|
38 var [x, y] = getBoundsForDOMElm(child); |
|
39 |
|
40 var actualChild = container.getChildAtPoint(x + 1, y + 1); |
|
41 isObject(actualChild, child, |
|
42 "Wrong direct child of " + prettyName(aContainerID)); |
|
43 |
|
44 var actualGrandChild = container.getDeepestChildAtPoint(x + 1, y + 1); |
|
45 isObject(actualGrandChild, grandChild, |
|
46 "Wrong deepest child of " + prettyName(aContainerID)); |
|
47 } |
|
48 |
|
49 /** |
|
50 * Test if getOffsetAtPoint returns the given text offset at given coordinates. |
|
51 */ |
|
52 function testOffsetAtPoint(aHyperTextID, aX, aY, aCoordType, aExpectedOffset) |
|
53 { |
|
54 var hyperText = getAccessible(aHyperTextID, [nsIAccessibleText]); |
|
55 var offset = hyperText.getOffsetAtPoint(aX, aY, aCoordType); |
|
56 is(offset, aExpectedOffset, |
|
57 "Wrong offset at given point (" + aX + ", " + aY + ") for " + |
|
58 prettyName(aHyperTextID)); |
|
59 } |
|
60 |
|
61 /** |
|
62 * Zoom the given document. |
|
63 */ |
|
64 function zoomDocument(aDocument, aZoom) |
|
65 { |
|
66 var docShell = aDocument.defaultView. |
|
67 QueryInterface(Components.interfaces.nsIInterfaceRequestor). |
|
68 getInterface(Components.interfaces.nsIWebNavigation). |
|
69 QueryInterface(Components.interfaces.nsIDocShell); |
|
70 var docViewer = docShell.contentViewer. |
|
71 QueryInterface(Components.interfaces.nsIMarkupDocumentViewer); |
|
72 |
|
73 docViewer.fullZoom = aZoom; |
|
74 } |
|
75 |
|
76 /** |
|
77 * Return child accessible at the given point. |
|
78 * |
|
79 * @param aIdentifier [in] accessible identifier |
|
80 * @param aX [in] x coordinate of the point relative accessible |
|
81 * @param aY [in] y coordinate of the point relative accessible |
|
82 * @param aFindDeepestChild [in] points whether deepest or nearest child should |
|
83 * be returned |
|
84 * @return the child accessible at the given point |
|
85 */ |
|
86 function getChildAtPoint(aIdentifier, aX, aY, aFindDeepestChild) |
|
87 { |
|
88 var acc = getAccessible(aIdentifier); |
|
89 if (!acc) |
|
90 return; |
|
91 |
|
92 var [screenX, screenY] = getBoundsForDOMElm(acc.DOMNode); |
|
93 |
|
94 var x = screenX + aX; |
|
95 var y = screenY + aY; |
|
96 |
|
97 try { |
|
98 if (aFindDeepestChild) |
|
99 return acc.getDeepestChildAtPoint(x, y); |
|
100 return acc.getChildAtPoint(x, y); |
|
101 } catch (e) { } |
|
102 |
|
103 return null; |
|
104 } |
|
105 |
|
106 /** |
|
107 * Test the accessible position. |
|
108 */ |
|
109 function testPos(aID, aPoint) |
|
110 { |
|
111 var [expectedX, expectedY] = |
|
112 (aPoint != undefined) ? aPoint : getBoundsForDOMElm(aID); |
|
113 |
|
114 var [x, y] = getBounds(aID); |
|
115 is(x, expectedX, "Wrong x coordinate of " + prettyName(aID)); |
|
116 is(y, expectedY, "Wrong y coordinate of " + prettyName(aID)); |
|
117 } |
|
118 |
|
119 /** |
|
120 * Test the accessible boundaries. |
|
121 */ |
|
122 function testBounds(aID, aRect) |
|
123 { |
|
124 var [expectedX, expectedY, expectedWidth, expectedHeight] = |
|
125 (aRect != undefined) ? aRect : getBoundsForDOMElm(aID); |
|
126 |
|
127 var [x, y, width, height] = getBounds(aID); |
|
128 is(x, expectedX, "Wrong x coordinate of " + prettyName(aID)); |
|
129 is(y, expectedY, "Wrong y coordinate of " + prettyName(aID)); |
|
130 is(width, expectedWidth, "Wrong width of " + prettyName(aID)); |
|
131 is(height, expectedHeight, "Wrong height of " + prettyName(aID)); |
|
132 } |
|
133 |
|
134 /** |
|
135 * Test text position at the given offset. |
|
136 */ |
|
137 function testTextPos(aID, aOffset, aPoint, aCoordOrigin) |
|
138 { |
|
139 var [expectedX, expectedY] = aPoint; |
|
140 |
|
141 var xObj = {}, yObj = {}; |
|
142 var hyperText = getAccessible(aID, [nsIAccessibleText]); |
|
143 hyperText.getCharacterExtents(aOffset, xObj, yObj, {}, {}, aCoordOrigin); |
|
144 is(xObj.value, expectedX, |
|
145 "Wrong x coordinate at offset " + aOffset + " for " + prettyName(aID)); |
|
146 ok(yObj.value - expectedY < 2 && expectedY - yObj.value < 2, |
|
147 "Wrong y coordinate at offset " + aOffset + " for " + prettyName(aID) + |
|
148 " - got " + yObj.value + ", expected " + expectedY + |
|
149 "The difference doesn't exceed 1."); |
|
150 } |
|
151 |
|
152 /** |
|
153 * Test text bounds that is enclosed betwene the given offsets. |
|
154 */ |
|
155 function testTextBounds(aID, aStartOffset, aEndOffset, aRect, aCoordOrigin) |
|
156 { |
|
157 var [expectedX, expectedY, expectedWidth, expectedHeight] = aRect; |
|
158 |
|
159 var xObj = {}, yObj = {}, widthObj = {}, heightObj = {}; |
|
160 var hyperText = getAccessible(aID, [nsIAccessibleText]); |
|
161 hyperText.getRangeExtents(aStartOffset, aEndOffset, |
|
162 xObj, yObj, widthObj, heightObj, aCoordOrigin); |
|
163 is(xObj.value, expectedX, |
|
164 "Wrong x coordinate of text between offsets (" + aStartOffset + ", " + |
|
165 aEndOffset + ") for " + prettyName(aID)); |
|
166 is(yObj.value, expectedY, |
|
167 "Wrong y coordinate of text between offsets (" + aStartOffset + ", " + |
|
168 aEndOffset + ") for " + prettyName(aID)); |
|
169 |
|
170 var msg = "Wrong width of text between offsets (" + aStartOffset + ", " + |
|
171 aEndOffset + ") for " + prettyName(aID); |
|
172 if (widthObj.value == expectedWidth) |
|
173 ok(true, msg); |
|
174 else |
|
175 todo(false, msg); // fails on some windows machines |
|
176 |
|
177 is(heightObj.value, expectedHeight, |
|
178 "Wrong height of text between offsets (" + aStartOffset + ", " + |
|
179 aEndOffset + ") for " + prettyName(aID)); |
|
180 } |
|
181 |
|
182 /** |
|
183 * Return the accessible coordinates relative to the screen in device pixels. |
|
184 */ |
|
185 function getPos(aID) |
|
186 { |
|
187 var accessible = getAccessible(aID); |
|
188 var x = {}, y = {}; |
|
189 accessible.getBounds(x, y, {}, {}); |
|
190 return [x.value, y.value]; |
|
191 } |
|
192 |
|
193 /** |
|
194 * Return the accessible coordinates and size relative to the screen in device |
|
195 * pixels. |
|
196 */ |
|
197 function getBounds(aID) |
|
198 { |
|
199 var accessible = getAccessible(aID); |
|
200 var x = {}, y = {}, width = {}, height = {}; |
|
201 accessible.getBounds(x, y, width, height); |
|
202 return [x.value, y.value, width.value, height.value]; |
|
203 } |
|
204 |
|
205 /** |
|
206 * Return DOM node coordinates relative the screen and its size in device |
|
207 * pixels. |
|
208 */ |
|
209 function getBoundsForDOMElm(aID) |
|
210 { |
|
211 var x = 0, y = 0, width = 0, height = 0; |
|
212 |
|
213 var elm = getNode(aID); |
|
214 if (elm.localName == "area") { |
|
215 var mapName = elm.parentNode.getAttribute("name"); |
|
216 var selector = "[usemap='#" + mapName + "']"; |
|
217 var img = elm.ownerDocument.querySelector(selector); |
|
218 |
|
219 var areaCoords = elm.coords.split(","); |
|
220 var areaX = parseInt(areaCoords[0]); |
|
221 var areaY = parseInt(areaCoords[1]); |
|
222 var areaWidth = parseInt(areaCoords[2]) - areaX; |
|
223 var areaHeight = parseInt(areaCoords[3]) - areaY; |
|
224 |
|
225 var rect = img.getBoundingClientRect(); |
|
226 x = rect.left + areaX; |
|
227 y = rect.top + areaY; |
|
228 width = areaWidth; |
|
229 height = areaHeight; |
|
230 } |
|
231 else { |
|
232 var rect = elm.getBoundingClientRect(); |
|
233 x = rect.left; |
|
234 y = rect.top; |
|
235 width = rect.width; |
|
236 height = rect.height; |
|
237 } |
|
238 |
|
239 var elmWindow = elm.ownerDocument.defaultView; |
|
240 return CSSToDevicePixels(elmWindow, |
|
241 x + elmWindow.mozInnerScreenX, |
|
242 y + elmWindow.mozInnerScreenY, |
|
243 width, |
|
244 height); |
|
245 } |
|
246 |
|
247 function CSSToDevicePixels(aWindow, aX, aY, aWidth, aHeight) |
|
248 { |
|
249 var winUtil = aWindow. |
|
250 QueryInterface(Components.interfaces.nsIInterfaceRequestor). |
|
251 getInterface(Components.interfaces.nsIDOMWindowUtils); |
|
252 |
|
253 var ratio = winUtil.screenPixelsPerCSSPixel; |
|
254 |
|
255 // CSS pixels and ratio can be not integer. Device pixels are always integer. |
|
256 // Do our best and hope it works. |
|
257 return [ Math.round(aX * ratio), Math.round(aY * ratio), |
|
258 Math.round(aWidth * ratio), Math.round(aHeight * ratio) ]; |
|
259 } |