Backed out 2 changesets (bug 1844171) for causing mochitest failures on browser_quickactions.js CLOSED TREE
Backed out changeset 2989a10ac4e6 (bug 1844171) Backed out changeset 9bc360cfb992 (bug 1844171)
This commit is contained in:
@@ -4,35 +4,42 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The Screenshots overlay is inserted into the document's
|
* The Screenshots overlay is inserted into the document's
|
||||||
* anonymous content container (see dom/webidl/Document.webidl).
|
* canvasFrame anonymous content container (see dom/webidl/Document.webidl).
|
||||||
*
|
*
|
||||||
* This container gets cleared automatically when the document navigates.
|
* This container gets cleared automatically when the document navigates.
|
||||||
*
|
*
|
||||||
|
* Since the overlay markup is inserted in the canvasFrame using
|
||||||
|
* insertAnonymousContent, this means that it can be modified using the API
|
||||||
|
* described in AnonymousContent.webidl.
|
||||||
|
*
|
||||||
|
* Any mutation of this content must be via the AnonymousContent API.
|
||||||
|
* This is similar in design to [devtools' highlighters](https://firefox-source-docs.mozilla.org/devtools/tools/highlighters.html#inserting-content-in-the-page),
|
||||||
|
* though as Screenshots doesnt need to work on XUL documents, or allow multiple kinds of
|
||||||
|
* highlight/overlay our case is a little simpler.
|
||||||
|
*
|
||||||
* To retrieve the AnonymousContent instance, use the `content` getter.
|
* To retrieve the AnonymousContent instance, use the `content` getter.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Below are the states of the screenshots overlay
|
|
||||||
* States:
|
|
||||||
* "crosshairs":
|
|
||||||
* Nothing has happened, and the crosshairs will follow the movement of the mouse
|
|
||||||
* "draggingReady":
|
|
||||||
* The user has pressed the mouse button, but hasn't moved enough to create a selection
|
|
||||||
* "dragging":
|
|
||||||
* The user has pressed down a mouse button, and is dragging out an area far enough to show a selection
|
|
||||||
* "selected":
|
|
||||||
* The user has selected an area
|
|
||||||
* "resizing":
|
|
||||||
* The user is resizing the selection
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {
|
/* States:
|
||||||
setMaxDetectHeight,
|
|
||||||
setMaxDetectWidth,
|
"crosshairs":
|
||||||
getBestRectForElement,
|
Nothing has happened, and the crosshairs will follow the movement of the mouse
|
||||||
Region,
|
"draggingReady":
|
||||||
WindowDimensions,
|
The user has pressed the mouse button, but hasn't moved enough to create a selection
|
||||||
} from "chrome://browser/content/screenshots/overlayHelpers.mjs";
|
"dragging":
|
||||||
|
The user has pressed down a mouse button, and is dragging out an area far enough to show a selection
|
||||||
|
"selected":
|
||||||
|
The user has selected an area
|
||||||
|
"resizing":
|
||||||
|
The user is resizing the selection
|
||||||
|
|
||||||
|
A pointerdown goes from crosshairs to dragging.
|
||||||
|
A pointerup goes from dragging to selected
|
||||||
|
A click outside of the selection goes from selected to crosshairs
|
||||||
|
A pointerdown on one of the draggers goes from selected to resizing
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
const lazy = {};
|
const lazy = {};
|
||||||
|
|
||||||
|
|||||||
@@ -1,414 +0,0 @@
|
|||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
// An autoselection smaller than these will be ignored entirely:
|
|
||||||
const MIN_DETECT_ABSOLUTE_HEIGHT = 10;
|
|
||||||
const MIN_DETECT_ABSOLUTE_WIDTH = 30;
|
|
||||||
// An autoselection smaller than these will not be preferred:
|
|
||||||
const MIN_DETECT_HEIGHT = 30;
|
|
||||||
const MIN_DETECT_WIDTH = 100;
|
|
||||||
// An autoselection bigger than either of these will be ignored:
|
|
||||||
let MAX_DETECT_HEIGHT = 700;
|
|
||||||
let MAX_DETECT_WIDTH = 1000;
|
|
||||||
|
|
||||||
const doNotAutoselectTags = {
|
|
||||||
H1: true,
|
|
||||||
H2: true,
|
|
||||||
H3: true,
|
|
||||||
H4: true,
|
|
||||||
H5: true,
|
|
||||||
H6: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the rect for an element if getBoundingClientRect exists
|
|
||||||
* @param ele The element to get the rect from
|
|
||||||
* @returns The bounding client rect of the element or null
|
|
||||||
*/
|
|
||||||
function getBoundingClientRect(ele) {
|
|
||||||
if (!ele.getBoundingClientRect) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ele.getBoundingClientRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setMaxDetectHeight(maxHeight) {
|
|
||||||
MAX_DETECT_HEIGHT = maxHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setMaxDetectWidth(maxWidth) {
|
|
||||||
MAX_DETECT_WIDTH = maxWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function takes an element and finds a suitable rect to draw the hover box on
|
|
||||||
* @param {Element} ele The element to find a suitale rect of
|
|
||||||
* @param {Document} doc The current document
|
|
||||||
* @returns A suitable rect or null
|
|
||||||
*/
|
|
||||||
export function getBestRectForElement(ele, doc) {
|
|
||||||
let lastRect;
|
|
||||||
let lastNode;
|
|
||||||
let rect;
|
|
||||||
let attemptExtend = false;
|
|
||||||
let node = ele;
|
|
||||||
while (node) {
|
|
||||||
rect = getBoundingClientRect(node);
|
|
||||||
if (!rect) {
|
|
||||||
rect = lastRect;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (rect.width < MIN_DETECT_WIDTH || rect.height < MIN_DETECT_HEIGHT) {
|
|
||||||
// Avoid infinite loop for elements with zero or nearly zero height,
|
|
||||||
// like non-clearfixed float parents with or without borders.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (rect.width > MAX_DETECT_WIDTH || rect.height > MAX_DETECT_HEIGHT) {
|
|
||||||
// Then the last rectangle is better
|
|
||||||
rect = lastRect;
|
|
||||||
attemptExtend = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (rect.width >= MIN_DETECT_WIDTH && rect.height >= MIN_DETECT_HEIGHT) {
|
|
||||||
if (!doNotAutoselectTags[node.tagName]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastRect = rect;
|
|
||||||
lastNode = node;
|
|
||||||
node = node.parentNode;
|
|
||||||
}
|
|
||||||
if (rect && node) {
|
|
||||||
const evenBetter = evenBetterElement(node, doc);
|
|
||||||
if (evenBetter) {
|
|
||||||
node = lastNode = evenBetter;
|
|
||||||
rect = getBoundingClientRect(evenBetter);
|
|
||||||
attemptExtend = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rect && attemptExtend) {
|
|
||||||
let extendNode = lastNode.nextSibling;
|
|
||||||
while (extendNode) {
|
|
||||||
if (extendNode.nodeType === doc.ELEMENT_NODE) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
extendNode = extendNode.nextSibling;
|
|
||||||
if (!extendNode) {
|
|
||||||
const parentNode = lastNode.parentNode;
|
|
||||||
for (let i = 0; i < parentNode.childNodes.length; i++) {
|
|
||||||
if (parentNode.childNodes[i] === lastNode) {
|
|
||||||
extendNode = parentNode.childNodes[i + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (extendNode) {
|
|
||||||
const extendRect = getBoundingClientRect(extendNode);
|
|
||||||
let x = Math.min(rect.x, extendRect.x);
|
|
||||||
let y = Math.min(rect.y, extendRect.y);
|
|
||||||
let width = Math.max(rect.right, extendRect.right) - x;
|
|
||||||
let height = Math.max(rect.bottom, extendRect.bottom) - y;
|
|
||||||
const combinedRect = new DOMRect(x, y, width, height);
|
|
||||||
if (
|
|
||||||
combinedRect.width <= MAX_DETECT_WIDTH &&
|
|
||||||
combinedRect.height <= MAX_DETECT_HEIGHT
|
|
||||||
) {
|
|
||||||
rect = combinedRect;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
rect &&
|
|
||||||
(rect.width < MIN_DETECT_ABSOLUTE_WIDTH ||
|
|
||||||
rect.height < MIN_DETECT_ABSOLUTE_HEIGHT)
|
|
||||||
) {
|
|
||||||
rect = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This finds a better element by looking for elements with role article
|
|
||||||
* @param {Element} node The currently hovered node
|
|
||||||
* @param {Document} doc The current document
|
|
||||||
* @returns A better node or null
|
|
||||||
*/
|
|
||||||
function evenBetterElement(node, doc) {
|
|
||||||
let el = node.parentNode;
|
|
||||||
const ELEMENT_NODE = doc.ELEMENT_NODE;
|
|
||||||
while (el && el.nodeType === ELEMENT_NODE) {
|
|
||||||
if (!el.getAttribute) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (el.getAttribute("role") === "article") {
|
|
||||||
const rect = getBoundingClientRect(el);
|
|
||||||
if (!rect) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (rect.width <= MAX_DETECT_WIDTH && rect.height <= MAX_DETECT_HEIGHT) {
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
el = el.parentNode;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Region {
|
|
||||||
#x1;
|
|
||||||
#x2;
|
|
||||||
#y1;
|
|
||||||
#y2;
|
|
||||||
#xOffset;
|
|
||||||
#yOffset;
|
|
||||||
#windowDimensions;
|
|
||||||
|
|
||||||
constructor(windowDimensions) {
|
|
||||||
this.resetDimensions();
|
|
||||||
this.#windowDimensions = windowDimensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the dimensions if the given dimension is defined.
|
|
||||||
* Otherwise will reset the dimensions
|
|
||||||
* @param {Object} dims The new region dimensions
|
|
||||||
* {
|
|
||||||
* left: new left dimension value or undefined
|
|
||||||
* top: new top dimension value or undefined
|
|
||||||
* right: new right dimension value or undefined
|
|
||||||
* bottom: new bottom dimension value or undefined
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
set dimensions(dims) {
|
|
||||||
if (dims == null) {
|
|
||||||
this.resetDimensions();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dims.left != null) {
|
|
||||||
this.left = dims.left;
|
|
||||||
}
|
|
||||||
if (dims.top != null) {
|
|
||||||
this.top = dims.top;
|
|
||||||
}
|
|
||||||
if (dims.right != null) {
|
|
||||||
this.right = dims.right;
|
|
||||||
}
|
|
||||||
if (dims.bottom != null) {
|
|
||||||
this.bottom = dims.bottom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get dimensions() {
|
|
||||||
return {
|
|
||||||
left: this.left,
|
|
||||||
top: this.top,
|
|
||||||
right: this.right,
|
|
||||||
bottom: this.bottom,
|
|
||||||
width: this.width,
|
|
||||||
height: this.height,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
get isRegionValid() {
|
|
||||||
return this.#x1 + this.#x2 + this.#y1 + this.#y2 > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetDimensions() {
|
|
||||||
this.#x1 = 0;
|
|
||||||
this.#x2 = 0;
|
|
||||||
this.#y1 = 0;
|
|
||||||
this.#y2 = 0;
|
|
||||||
this.#xOffset = 0;
|
|
||||||
this.#yOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort the coordinates so x1 < x2 and y1 < y2
|
|
||||||
*/
|
|
||||||
sortCoords() {
|
|
||||||
if (this.#x1 > this.#x2) {
|
|
||||||
[this.#x1, this.#x2] = [this.#x2, this.#x1];
|
|
||||||
}
|
|
||||||
if (this.#y1 > this.#y2) {
|
|
||||||
[this.#y1, this.#y2] = [this.#y2, this.#y1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The region should never appear outside the document so the region will
|
|
||||||
* be shifted if the region is outside the page's width or height.
|
|
||||||
*/
|
|
||||||
shift() {
|
|
||||||
let didShift = false;
|
|
||||||
let xDiff = this.right - this.#windowDimensions.scrollWidth;
|
|
||||||
if (xDiff > 0) {
|
|
||||||
this.right -= xDiff;
|
|
||||||
this.left -= xDiff;
|
|
||||||
|
|
||||||
didShift = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let yDiff = this.bottom - this.#windowDimensions.scrollHeight;
|
|
||||||
if (yDiff > 0) {
|
|
||||||
let curHeight = this.height;
|
|
||||||
|
|
||||||
this.bottom -= yDiff;
|
|
||||||
this.top = this.bottom - curHeight;
|
|
||||||
|
|
||||||
didShift = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return didShift;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The diagonal distance of the region
|
|
||||||
*/
|
|
||||||
get distance() {
|
|
||||||
return Math.sqrt(Math.pow(this.width, 2) + Math.pow(this.height, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
get xOffset() {
|
|
||||||
return this.#xOffset;
|
|
||||||
}
|
|
||||||
set xOffset(val) {
|
|
||||||
this.#xOffset = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
get yOffset() {
|
|
||||||
return this.#yOffset;
|
|
||||||
}
|
|
||||||
set yOffset(val) {
|
|
||||||
this.#yOffset = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
get top() {
|
|
||||||
return Math.min(this.#y1, this.#y2);
|
|
||||||
}
|
|
||||||
set top(val) {
|
|
||||||
this.#y1 = val > 0 ? val : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
get left() {
|
|
||||||
return Math.min(this.#x1, this.#x2);
|
|
||||||
}
|
|
||||||
set left(val) {
|
|
||||||
this.#x1 = val > 0 ? val : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
get right() {
|
|
||||||
return Math.max(this.#x1, this.#x2);
|
|
||||||
}
|
|
||||||
set right(val) {
|
|
||||||
this.#x2 =
|
|
||||||
val > this.#windowDimensions.scrollWidth
|
|
||||||
? this.#windowDimensions.scrollWidth
|
|
||||||
: val;
|
|
||||||
}
|
|
||||||
|
|
||||||
get bottom() {
|
|
||||||
return Math.max(this.#y1, this.#y2);
|
|
||||||
}
|
|
||||||
set bottom(val) {
|
|
||||||
this.#y2 =
|
|
||||||
val > this.#windowDimensions.scrollHeight
|
|
||||||
? this.#windowDimensions.scrollHeight
|
|
||||||
: val;
|
|
||||||
}
|
|
||||||
|
|
||||||
get width() {
|
|
||||||
return Math.abs(this.#x2 - this.#x1);
|
|
||||||
}
|
|
||||||
get height() {
|
|
||||||
return Math.abs(this.#y2 - this.#y1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class WindowDimensions {
|
|
||||||
#clientHeight = null;
|
|
||||||
#clientWidth = null;
|
|
||||||
#scrollHeight = null;
|
|
||||||
#scrollWidth = null;
|
|
||||||
#scrollX = null;
|
|
||||||
#scrollY = null;
|
|
||||||
#scrollMinX = null;
|
|
||||||
#scrollMinY = null;
|
|
||||||
|
|
||||||
set dimensions(dimensions) {
|
|
||||||
if (dimensions.clientHeight) {
|
|
||||||
this.#clientHeight = dimensions.clientHeight;
|
|
||||||
}
|
|
||||||
if (dimensions.clientWidth) {
|
|
||||||
this.#clientWidth = dimensions.clientWidth;
|
|
||||||
}
|
|
||||||
if (dimensions.scrollHeight) {
|
|
||||||
this.#scrollHeight = dimensions.scrollHeight;
|
|
||||||
}
|
|
||||||
if (dimensions.scrollWidth) {
|
|
||||||
this.#scrollWidth = dimensions.scrollWidth;
|
|
||||||
}
|
|
||||||
if (dimensions.scrollX) {
|
|
||||||
this.#scrollX = dimensions.scrollX;
|
|
||||||
}
|
|
||||||
if (dimensions.scrollY) {
|
|
||||||
this.#scrollY = dimensions.scrollY;
|
|
||||||
}
|
|
||||||
if (dimensions.scrollMinX) {
|
|
||||||
this.#scrollMinX = dimensions.scrollMinX;
|
|
||||||
}
|
|
||||||
if (dimensions.scrollMinY) {
|
|
||||||
this.#scrollMinY = dimensions.scrollMinY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get dimensions() {
|
|
||||||
return {
|
|
||||||
clientHeight: this.#clientHeight,
|
|
||||||
clientWidth: this.#clientWidth,
|
|
||||||
scrollHeight: this.#scrollHeight,
|
|
||||||
scrollWidth: this.#scrollWidth,
|
|
||||||
scrollX: this.#scrollX,
|
|
||||||
scrollY: this.#scrollY,
|
|
||||||
scrollMinX: this.#scrollMinX,
|
|
||||||
scrollMinY: this.#scrollMinY,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
get clientWidth() {
|
|
||||||
return this.#clientWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
get clientHeight() {
|
|
||||||
return this.#clientHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
get scrollWidth() {
|
|
||||||
return this.#scrollWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
get scrollHeight() {
|
|
||||||
return this.#scrollHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
get scrollX() {
|
|
||||||
return this.#scrollX;
|
|
||||||
}
|
|
||||||
|
|
||||||
get scrollY() {
|
|
||||||
return this.#scrollY;
|
|
||||||
}
|
|
||||||
|
|
||||||
get scrollMinX() {
|
|
||||||
return this.#scrollMinX;
|
|
||||||
}
|
|
||||||
|
|
||||||
get scrollMinY() {
|
|
||||||
return this.#scrollMinY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user