Bug 1872764 - Screenshots should always get events. r=sfoster,emilio

Differential Revision: https://phabricator.services.mozilla.com/D197802
This commit is contained in:
Niklas Baumgardner 2024-01-12 02:24:43 +00:00
parent 44523c0504
commit 10e944bf30
6 changed files with 97 additions and 66 deletions

View file

@ -15,6 +15,15 @@ export class ScreenshotsComponentChild extends JSWindowActorChild {
#scrollTask;
#overlay;
static OVERLAY_EVENTS = [
"click",
"pointerdown",
"pointermove",
"pointerup",
"keyup",
"keydown",
];
get overlay() {
return this.#overlay;
}
@ -41,10 +50,19 @@ export class ScreenshotsComponentChild extends JSWindowActorChild {
handleEvent(event) {
switch (event.type) {
case "click":
case "pointerdown":
case "pointermove":
case "pointerup":
case "keyup":
case "keydown":
if (event.key === "Escape") {
if (!this.overlay?.initialized) {
return;
}
if (event.type === "keydown" && event.key === "Escape") {
this.requestCancelScreenshot("escape");
}
this.overlay.handleEvent(event);
break;
case "beforeunload":
this.requestCancelScreenshot("navigation");
@ -191,6 +209,13 @@ export class ScreenshotsComponentChild extends JSWindowActorChild {
});
}
addOverlayEventListeners() {
let chromeEventHandler = this.docShell.chromeEventHandler;
for (let event of ScreenshotsComponentChild.OVERLAY_EVENTS) {
chromeEventHandler.addEventListener(event, this, true);
}
}
/**
* Wait until the document is ready and then show the screenshots overlay
*
@ -208,24 +233,33 @@ export class ScreenshotsComponentChild extends JSWindowActorChild {
let overlay =
this.overlay ||
(this.#overlay = new lazy.ScreenshotsOverlay(this.document));
this.document.addEventListener("keydown", this);
this.document.ownerGlobal.addEventListener("beforeunload", this);
this.contentWindow.addEventListener("resize", this);
this.contentWindow.addEventListener("scroll", this);
this.contentWindow.addEventListener("visibilitychange", this);
this.addOverlayEventListeners();
overlay.initialize();
return true;
}
removeOverlayEventListeners() {
let chromeEventHandler = this.docShell.chromeEventHandler;
for (let event of ScreenshotsComponentChild.OVERLAY_EVENTS) {
chromeEventHandler.removeEventListener(event, this, true);
}
}
/**
* Removes event listeners and the screenshots overlay.
*/
endScreenshotsOverlay(options = {}) {
this.document.removeEventListener("keydown", this);
this.document.ownerGlobal.removeEventListener("beforeunload", this);
this.contentWindow.removeEventListener("resize", this);
this.contentWindow.removeEventListener("scroll", this);
this.contentWindow.removeEventListener("visibilitychange", this);
this.removeOverlayEventListeners();
this.overlay?.tearDown(options);
this.#resizeTask?.disarm();
this.#scrollTask?.disarm();

View file

@ -229,8 +229,6 @@ export class ScreenshotsOverlay {
this.bottomRightMover = this.getElementById("mover-bottomRight");
this.selectionSize = this.getElementById("selection-size");
this.addEventListeners();
}
/**
@ -238,7 +236,6 @@ export class ScreenshotsOverlay {
*/
tearDown(options = {}) {
if (this.#content) {
this.removeEventListeners();
if (!(options.doNotResetMethods === true)) {
this.resetMethodsUsed();
}
@ -253,30 +250,6 @@ export class ScreenshotsOverlay {
this.#setState("");
}
/**
* Add required event listeners to the overlay
*/
addEventListeners() {
this.screenshotsContainer.addEventListener("click", this);
this.screenshotsContainer.addEventListener("pointerdown", this);
this.window.addEventListener("pointermove", this);
this.window.addEventListener("pointerup", this);
this.screenshotsContainer.addEventListener("keydown", this);
this.screenshotsContainer.addEventListener("keyup", this);
}
/**
* Remove the events listeners from the overlay
*/
removeEventListeners() {
this.screenshotsContainer.removeEventListener("click", this);
this.screenshotsContainer.removeEventListener("pointerdown", this);
this.window.removeEventListener("pointermove", this);
this.window.removeEventListener("pointerup", this);
this.screenshotsContainer.removeEventListener("keydown", this);
this.screenshotsContainer.removeEventListener("keyup", this);
}
resetMethodsUsed() {
this.#methodsUsed = {
element: 0,
@ -332,7 +305,7 @@ export class ScreenshotsOverlay {
}
handleClick(event) {
switch (event.target.id) {
switch (event.originalTarget.id) {
case "screenshots-cancel-button":
case "cancel":
this.#dispatchEvent("Screenshots:Close", { reason: "overlay_cancel" });
@ -357,8 +330,9 @@ export class ScreenshotsOverlay {
*/
handlePointerDown(event) {
if (
event.target.id === "screenshots-cancel-button" ||
event.target.closest("#buttons-container") === this.buttonsContainer
event.originalTarget.id === "screenshots-cancel-button" ||
event.originalTarget.closest("#buttons-container") ===
this.buttonsContainer
) {
event.stopPropagation();
return;
@ -372,7 +346,7 @@ export class ScreenshotsOverlay {
break;
}
case STATES.SELECTED: {
this.selectedDragStart(pageX, pageY, event.target.id);
this.selectedDragStart(pageX, pageY, event.originalTarget.id);
break;
}
}
@ -420,7 +394,7 @@ export class ScreenshotsOverlay {
break;
}
case STATES.DRAGGING: {
this.draggingDragEnd(pageX, pageY, event.target.id);
this.draggingDragEnd(pageX, pageY, event.originalTarget.id);
break;
}
case STATES.RESIZING: {
@ -475,7 +449,7 @@ export class ScreenshotsOverlay {
* @param {Event} event The keydown event
*/
handleArrowLeftKeyDown(event) {
switch (event.target.id) {
switch (event.originalTarget.id) {
case "highlight":
if (this.getAccelKey(event)) {
let width = this.selectionRegion.width;
@ -505,9 +479,9 @@ export class ScreenshotsOverlay {
let left = this.selectionRegion.left;
this.selectionRegion.left = this.windowDimensions.scrollX;
this.selectionRegion.right = left;
if (event.target.id === "mover-topRight") {
if (event.originalTarget.id === "mover-topRight") {
this.topLeftMover.focus();
} else if (event.target.id === "mover-bottomRight") {
} else if (event.originalTarget.id === "mover-bottomRight") {
this.bottomLeftMover.focus();
}
break;
@ -516,9 +490,9 @@ export class ScreenshotsOverlay {
this.selectionRegion.right -= 10 ** event.shiftKey;
if (this.selectionRegion.x1 >= this.selectionRegion.x2) {
this.selectionRegion.sortCoords();
if (event.target.id === "mover-topRight") {
if (event.originalTarget.id === "mover-topRight") {
this.topLeftMover.focus();
} else if (event.target.id === "mover-bottomRight") {
} else if (event.originalTarget.id === "mover-bottomRight") {
this.bottomLeftMover.focus();
}
}
@ -543,7 +517,7 @@ export class ScreenshotsOverlay {
* @param {Event} event The keydown event
*/
handleArrowUpKeyDown(event) {
switch (event.target.id) {
switch (event.originalTarget.id) {
case "highlight":
if (this.getAccelKey(event)) {
let height = this.selectionRegion.height;
@ -573,9 +547,9 @@ export class ScreenshotsOverlay {
let top = this.selectionRegion.top;
this.selectionRegion.top = this.windowDimensions.scrollY;
this.selectionRegion.bottom = top;
if (event.target.id === "mover-bottomLeft") {
if (event.originalTarget.id === "mover-bottomLeft") {
this.topLeftMover.focus();
} else if (event.target.id === "mover-bottomRight") {
} else if (event.originalTarget.id === "mover-bottomRight") {
this.topRightMover.focus();
}
break;
@ -584,9 +558,9 @@ export class ScreenshotsOverlay {
this.selectionRegion.bottom -= 10 ** event.shiftKey;
if (this.selectionRegion.y1 >= this.selectionRegion.y2) {
this.selectionRegion.sortCoords();
if (event.target.id === "mover-bottomLeft") {
if (event.originalTarget.id === "mover-bottomLeft") {
this.topLeftMover.focus();
} else if (event.target.id === "mover-bottomRight") {
} else if (event.originalTarget.id === "mover-bottomRight") {
this.topRightMover.focus();
}
}
@ -611,7 +585,7 @@ export class ScreenshotsOverlay {
* @param {Event} event The keydown event
*/
handleArrowRightKeyDown(event) {
switch (event.target.id) {
switch (event.originalTarget.id) {
case "highlight":
if (this.getAccelKey(event)) {
let width = this.selectionRegion.width;
@ -644,9 +618,9 @@ export class ScreenshotsOverlay {
this.selectionRegion.right =
this.windowDimensions.scrollX + this.windowDimensions.clientWidth;
this.selectionRegion.left = right;
if (event.target.id === "mover-topLeft") {
if (event.originalTarget.id === "mover-topLeft") {
this.topRightMover.focus();
} else if (event.target.id === "mover-bottomLeft") {
} else if (event.originalTarget.id === "mover-bottomLeft") {
this.bottomRightMover.focus();
}
break;
@ -655,9 +629,9 @@ export class ScreenshotsOverlay {
this.selectionRegion.left += 10 ** event.shiftKey;
if (this.selectionRegion.x1 >= this.selectionRegion.x2) {
this.selectionRegion.sortCoords();
if (event.target.id === "mover-topLeft") {
if (event.originalTarget.id === "mover-topLeft") {
this.topRightMover.focus();
} else if (event.target.id === "mover-bottomLeft") {
} else if (event.originalTarget.id === "mover-bottomLeft") {
this.bottomRightMover.focus();
}
}
@ -682,7 +656,7 @@ export class ScreenshotsOverlay {
* @param {Event} event The keydown event
*/
handleArrowDownKeyDown(event) {
switch (event.target.id) {
switch (event.originalTarget.id) {
case "highlight":
if (this.getAccelKey(event)) {
let height = this.selectionRegion.height;
@ -715,9 +689,9 @@ export class ScreenshotsOverlay {
this.selectionRegion.bottom =
this.windowDimensions.scrollY + this.windowDimensions.clientHeight;
this.selectionRegion.top = bottom;
if (event.target.id === "mover-topLeft") {
if (event.originalTarget.id === "mover-topLeft") {
this.bottomLeftMover.focus();
} else if (event.target.id === "mover-topRight") {
} else if (event.originalTarget.id === "mover-topRight") {
this.bottomRightMover.focus();
}
break;
@ -726,9 +700,9 @@ export class ScreenshotsOverlay {
this.selectionRegion.top += 10 ** event.shiftKey;
if (this.selectionRegion.y1 >= this.selectionRegion.y2) {
this.selectionRegion.sortCoords();
if (event.target.id === "mover-topLeft") {
if (event.originalTarget.id === "mover-topLeft") {
this.bottomLeftMover.focus();
} else if (event.target.id === "mover-topRight") {
} else if (event.originalTarget.id === "mover-topRight") {
this.bottomRightMover.focus();
}
}
@ -755,12 +729,18 @@ export class ScreenshotsOverlay {
return;
}
if (event.target.id === "highlight" && event.shiftKey) {
event.preventDefault();
event.preventDefault();
if (event.originalTarget.id === "highlight" && event.shiftKey) {
this.downloadButton.focus();
} else if (event.target.id === "download" && !event.shiftKey) {
event.preventDefault();
} else if (event.originalTarget.id === "download" && !event.shiftKey) {
this.highlightEl.focus();
} else {
// The content document can listen for keydown events and prevent moving
// focus so we manually move focus to the next element here.
let direction = event.shiftKey
? Services.focus.MOVEFOCUS_BACKWARD
: Services.focus.MOVEFOCUS_FORWARD;
Services.focus.moveFocus(this.window, null, direction, 0);
}
}
@ -775,7 +755,7 @@ export class ScreenshotsOverlay {
case "ArrowUp":
case "ArrowRight":
case "ArrowDown":
switch (event.target.id) {
switch (event.originalTarget.id) {
case "highlight":
case "mover-bottomLeft":
case "mover-bottomRight":

View file

@ -12,11 +12,11 @@ add_task(async function test() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: TEST_PAGE,
url: SHORT_TEST_PAGE,
},
async browser => {
await clearAllTelemetryEvents();
await SpecialPowers.spawn(browser, [TEST_PAGE], url => {
await SpecialPowers.spawn(browser, [SHORT_TEST_PAGE], url => {
let a = content.document.createElement("a");
a.id = "clickMe";
a.href = url;

View file

@ -92,7 +92,7 @@ add_task(async function test_started_and_canceled_events() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: TEST_PAGE,
url: SHORT_TEST_PAGE,
},
async browser => {
await clearAllTelemetryEvents();

View file

@ -34,7 +34,7 @@ add_task(async function test() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: TEST_PAGE,
url: SHORT_TEST_PAGE,
},
async browser => {
function awaitExtensionEvent(eventName, id) {
@ -227,7 +227,7 @@ add_task(async function test() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: TEST_PAGE,
url: SHORT_TEST_PAGE,
},
async browser => {
const SCREENSHOTS_PREF = "extensions.screenshots.disabled";
@ -265,7 +265,7 @@ add_task(async function test() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: TEST_PAGE,
url: SHORT_TEST_PAGE,
},
async browser => {
const SCREENSHOTS_PREF = "extensions.screenshots.disabled";

View file

@ -6,5 +6,22 @@
</head>
<body style="height:4000px; width:4000px; background-repeat: no-repeat; background-size: 4008px 4016px; background-color: rgb(111, 111, 111); background-image:linear-gradient(to right, transparent 50%, rgba(0, 200, 200, 0.5) 50%),linear-gradient(to bottom, transparent 50%, rgba(100, 0, 100, 0.5) 50%);">
<div id="testPageElement" style="position:absolute; top:91px; left:93px; width:92px; height:94px; border:solid red;"></div>
<script>
// Make sure the screenshots overlay anonymous document always receives events
// that web content would normally be able to intercept, as that could break the
// overlay
function disabledEvent(event) {
event.preventDefault();
event.stopImmediatePropagation();
}
window.addEventListener("click", disabledEvent, true);
window.addEventListener("pointerdown", disabledEvent, true);
window.addEventListener("pointermove", disabledEvent, true);
window.addEventListener("mousemove", disabledEvent, true);
window.addEventListener("pointerup", disabledEvent, true);
window.addEventListener("keydown", disabledEvent, true);
window.addEventListener("keyup", disabledEvent, true);
</script>
</body>
</html>