Layout.sys.mjs (4899B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 import { Assert } from "resource://testing-common/Assert.sys.mjs"; 6 7 import { CommonUtils } from "chrome://mochitests/content/browser/accessible/tests/browser/Common.sys.mjs"; 8 9 export const Layout = { 10 /** 11 * Zoom the given document. 12 */ 13 zoomDocument(doc, zoom) { 14 const bc = BrowsingContext.getFromWindow(doc.defaultView); 15 // To mirror the behaviour of the UI, we set the zoom 16 // value on the top level browsing context. This value automatically 17 // propagates down to iframes. 18 bc.top.fullZoom = zoom; 19 }, 20 21 /** 22 * Set the relative resolution of this document. This is what apz does. 23 * On non-mobile platforms you won't see a visible change. 24 */ 25 setResolution(doc, zoom) { 26 const windowUtils = doc.defaultView.windowUtils; 27 windowUtils.setResolutionAndScaleTo(zoom); 28 }, 29 30 /** 31 * Assert.is() function checking the expected value is within the range. 32 */ 33 isWithin(expected, got, within, msg) { 34 if (Math.abs(got - expected) <= within) { 35 Assert.ok(true, `${msg} - Got ${got}`); 36 } else { 37 Assert.ok( 38 false, 39 `${msg} - Got ${got}, expected ${expected} with error of ${within}` 40 ); 41 } 42 }, 43 44 /** 45 * Return the accessible coordinates relative to the screen in device pixels. 46 */ 47 getPos(id) { 48 const accessible = CommonUtils.getAccessible(id); 49 const x = {}; 50 const y = {}; 51 accessible.getBounds(x, y, {}, {}); 52 53 return [x.value, y.value]; 54 }, 55 56 /** 57 * Return the accessible coordinates and size relative to the screen in device 58 * pixels. This methods also retrieves coordinates in CSS pixels and ensures that they 59 * match Dev pixels with a given device pixel ratio. 60 */ 61 getBounds(id, dpr) { 62 const accessible = CommonUtils.getAccessible(id); 63 const x = {}; 64 const y = {}; 65 const width = {}; 66 const height = {}; 67 const xInCSS = {}; 68 const yInCSS = {}; 69 const widthInCSS = {}; 70 const heightInCSS = {}; 71 accessible.getBounds(x, y, width, height); 72 accessible.getBoundsInCSSPixels(xInCSS, yInCSS, widthInCSS, heightInCSS); 73 74 this.isWithin( 75 x.value / dpr, 76 xInCSS.value, 77 1, 78 "X in CSS pixels is calculated correctly" 79 ); 80 this.isWithin( 81 y.value / dpr, 82 yInCSS.value, 83 1, 84 "Y in CSS pixels is calculated correctly" 85 ); 86 this.isWithin( 87 width.value / dpr, 88 widthInCSS.value, 89 1, 90 "Width in CSS pixels is calculated correctly" 91 ); 92 this.isWithin( 93 height.value / dpr, 94 heightInCSS.value, 95 1, 96 "Height in CSS pixels is calculated correctly" 97 ); 98 99 return [x.value, y.value, width.value, height.value]; 100 }, 101 102 getRangeExtents(id, startOffset, endOffset, coordOrigin) { 103 const hyperText = CommonUtils.getAccessible(id, [Ci.nsIAccessibleText]); 104 const x = {}; 105 const y = {}; 106 const width = {}; 107 const height = {}; 108 hyperText.getRangeExtents( 109 startOffset, 110 endOffset, 111 x, 112 y, 113 width, 114 height, 115 coordOrigin 116 ); 117 118 return [x.value, y.value, width.value, height.value]; 119 }, 120 121 CSSToDevicePixels(win, x, y, width, height) { 122 const ratio = win.devicePixelRatio; 123 124 // CSS pixels and ratio can be not integer. Device pixels are always integer. 125 // Do our best and hope it works. 126 return [ 127 Math.round(x * ratio), 128 Math.round(y * ratio), 129 Math.round(width * ratio), 130 Math.round(height * ratio), 131 ]; 132 }, 133 134 /** 135 * Return DOM node coordinates relative the screen and its size in device 136 * pixels. 137 */ 138 getBoundsForDOMElm(id, doc) { 139 let x = 0; 140 let y = 0; 141 let width = 0; 142 let height = 0; 143 144 const elm = CommonUtils.getNode(id, doc); 145 const elmWindow = elm.ownerGlobal; 146 if (elm.localName == "area") { 147 const mapName = elm.parentNode.getAttribute("name"); 148 const selector = `[usemap="#${mapName}"]`; 149 const img = elm.ownerDocument.querySelector(selector); 150 151 const areaCoords = elm.coords.split(","); 152 const areaX = parseInt(areaCoords[0], 10); 153 const areaY = parseInt(areaCoords[1], 10); 154 const areaWidth = parseInt(areaCoords[2], 10) - areaX; 155 const areaHeight = parseInt(areaCoords[3], 10) - areaY; 156 157 const rect = img.getBoundingClientRect(); 158 x = rect.left + areaX; 159 y = rect.top + areaY; 160 width = areaWidth; 161 height = areaHeight; 162 } else { 163 const rect = elm.getBoundingClientRect(); 164 x = rect.left; 165 y = rect.top; 166 width = rect.width; 167 height = rect.height; 168 } 169 170 return this.CSSToDevicePixels( 171 elmWindow, 172 x + elmWindow.mozInnerScreenX, 173 y + elmWindow.mozInnerScreenY, 174 width, 175 height 176 ); 177 }, 178 };