Bug 1725540 - Use nsIDOMWindowUtils.toScreenRect to get positions in the screen coords to avoid accessing window.top directly. r=tnikkel

Differential Revision: https://phabricator.services.mozilla.com/D122560
This commit is contained in:
Hiroyuki Ikezoe 2021-08-19 07:51:28 +00:00
Родитель 77ade58a2b
Коммит 9e78018010
2 изменённых файлов: 57 добавлений и 43 удалений

Просмотреть файл

@ -193,7 +193,7 @@ function getBoundingClientRectRelativeToVisualViewport(aElement) {
// |aTarget| may be an element (contained in the root content document or
// a subdocument) or, as a special case, the root content window.
// FIXME: Support iframe windows as targets.
function getTargetRect(aTarget) {
function _getTargetRect(aTarget) {
let rect = { left: 0, top: 0, width: 0, height: 0 };
// If the target is the root content window, its origin relative
@ -258,19 +258,18 @@ function getTargetRect(aTarget) {
aTarget = iframe;
}
// Now we have coordinates relative to the root content document's
// layout viewport. Subtract the offset of the visual viewport
// relative to the layout viewport, to get coordinates relative to
// the visual viewport.
var offsetX = {},
offsetY = {};
let rootUtils = SpecialPowers.getDOMWindowUtils(window.top);
rootUtils.getVisualViewportOffsetRelativeToLayoutViewport(offsetX, offsetY);
rect.left -= offsetX.value;
rect.top -= offsetY.value;
return rect;
}
// Returns the in-process root window for the given |aWindow|.
function getInProcessRootWindow(aWindow) {
let window = aWindow;
while (window.frameElement) {
window = window.frameElement.ownerDocument.defaultView;
}
return window;
}
// Convert (offsetX, offsetY) of target or center of it, in CSS pixels to device
// pixels relative to the screen.
// TODO: this function currently does not incorporate some CSS transforms on
@ -290,31 +289,53 @@ async function coordinatesRelativeToScreen(aParams) {
// harness.
// 2. The mochitest itself creates an iframe and calls this function from
// script running in the context of the iframe.
// Since the resolution applies to the root content document, below we use
// the mozInnerScreen{X,Y} of the root content window (window.top) only,
// and factor any offsets between iframe windows and the root content window
// into |origin|.
const utils = SpecialPowers.getDOMWindowUtils(window);
const deviceScale = utils.screenPixelsPerCSSPixel;
const deviceScaleNoOverride = utils.screenPixelsPerCSSPixelNoOverride;
const resolution = await getResolution();
const rect = getTargetRect(target);
// moxInnerScreen{X,Y} are in CSS coordinates of the browser chrome.
// The device scale applies to them, but the resolution only zooms the content.
// In addition, if we're inside RDM, RDM overrides the device scale;
// the overridden scale only applies to the content inside the RDM
// document, not to mozInnerScreen{X,Y}.
// Since the resolution applies to the top level content document, below we
// use the mozInnerScreen{X,Y} of the top level content window (window.top)
// only for the case where this function gets called in the top level content
// document. In other cases we use nsIDOMWindowUtils.toScreenRect().
// We do often specify `window` as the target, if it's the top level window,
// `nsIDOMWindowUtils.toScreenRect` isn't suitable because the function is
// supposed to be called with values in the document coords, so for example
// if desktop zoom is being applied, (0, 0) in the document coords might be
// outside of the visual viewport, i.e. it's going to be negative with the
// `toScreenRect` conversion, whereas the call sites with `window` of this
// function expect (0, 0) position should be the visual viport's offset. So
// in such cases we simply use mozInnerScreen{X,Y} to convert the given value
// to the screen coords.
if (target instanceof Window && window.parent == window) {
// moxInnerScreen{X,Y} are in CSS coordinates of the browser chrome.
// The device scale applies to them, but the resolution only zooms the content.
// In addition, if we're inside RDM, RDM overrides the device scale;
// the overridden scale only applies to the content inside the RDM
// document, not to mozInnerScreen{X,Y}.
const utils = SpecialPowers.getDOMWindowUtils(window);
const resolution = await getResolution();
const deviceScale = utils.screenPixelsPerCSSPixel;
const deviceScaleNoOverride = utils.screenPixelsPerCSSPixelNoOverride;
return {
x:
window.mozInnerScreenX * deviceScaleNoOverride +
(atCenter ? 0 : offsetX) * resolution * deviceScale,
y:
window.mozInnerScreenY * deviceScaleNoOverride +
(atCenter ? 0 : offsetY) * resolution * deviceScale,
};
}
const rect = _getTargetRect(target);
const utils = SpecialPowers.getDOMWindowUtils(getInProcessRootWindow(window));
const positionInScreenCoords = utils.toScreenRect(
rect.left + (atCenter ? rect.width / 2 : offsetX),
rect.top + (atCenter ? rect.height / 2 : offsetY),
0,
0
);
return {
x:
window.top.mozInnerScreenX * deviceScaleNoOverride +
(rect.left + (atCenter ? rect.width / 2 : offsetX)) *
resolution *
deviceScale,
y:
window.top.mozInnerScreenY * deviceScaleNoOverride +
(rect.top + (atCenter ? rect.height / 2 : offsetY)) *
resolution *
deviceScale,
x: positionInScreenCoords.x,
y: positionInScreenCoords.y,
};
}

Просмотреть файл

@ -14,16 +14,13 @@
[test_bug1151667.html]
skip-if =
os == 'android' # wheel events not supported on mobile
xorigin # JavaScript error: , line 0: uncaught exception: Object
[test_bug1253683.html]
skip-if =
os == 'android' # wheel events not supported on mobile
verify && debug && os == 'linux'
xorigin # JavaScript error: , line 0: uncaught exception: Object
[test_bug1277814.html]
skip-if =
os == 'android' # wheel events not supported on mobile
xorigin # JavaScript error: , line 0: uncaught exception: Object
[test_bug1304689.html]
[test_bug1304689-2.html]
[test_group_bug1464568.html]
@ -67,11 +64,10 @@
skip-if =
os == 'android' # wheel events not supported on mobile
os == 'linux' && fission && headless # Bug 1722907
xorigin # JavaScript error: , line 0: uncaught exception: Object
xorigin # "scrolling 'inner2' should cause it to be directly activated" etc.
[test_relative_update.html]
skip-if =
os == 'android' # wheel events not supported on mobile
xorigin # JavaScript error: , line 0: uncaught exception: Object
[test_scroll_inactive_bug1190112.html]
skip-if = (os == 'android') # wheel events not supported on mobile
[test_scroll_inactive_flattened_frame.html]
@ -82,15 +78,12 @@
skip-if =
toolkit == 'android' # wheel events not supported on mobile
toolkit == 'cocoa' # synthesized wheel smooth-scrolling not supported on OS X
xorigin # JavaScript error: , line 0: uncaught exception: Object
[test_wheel_scroll.html]
skip-if =
os == 'android' # wheel events not supported on mobile
xorigin # JavaScript error: , line 0: uncaught exception: Object
[test_wheel_transactions.html]
skip-if =
toolkit == 'android' # wheel events not supported on mobile
xorigin # JavaScript error: , line 0: uncaught exception: Object
[test_group_overrides.html]
skip-if =
toolkit == 'android' # wheel events not supported on mobile