--- a/devtools/server/actors/highlighters/eye-dropper.js
+++ b/devtools/server/actors/highlighters/eye-dropper.js
@@ -130,16 +130,20 @@ EyeDropper.prototype = {
return false;
}
this.options = options;
// Get the page's current zoom level.
this.pageZoom = getCurrentZoom(this.win);
+ // Focus the content so the keyboard can be used, and so that any focused
+ // elements are drawn as such.
+ this.win.focus();
+
// Take a screenshot of the viewport. This needs to be done first otherwise the
// eyedropper UI will appear in the screenshot itself (since the UI is injected as
// native anonymous content in the page).
// Once the screenshot is ready, the magnified area will be drawn.
this.prepareImageCapture();
// Start listening for user events.
let {pageListenerTarget} = this.highlighterEnv;
@@ -156,19 +160,16 @@ EyeDropper.prototype = {
this.ctx = this.getElement("canvas").getCanvasContext();
this.ctx.imageSmoothingEnabled = false;
this.magnifiedArea = {width: MAGNIFIER_WIDTH, height: MAGNIFIER_HEIGHT,
x: DEFAULT_START_POS_X, y: DEFAULT_START_POS_Y};
this.moveTo(DEFAULT_START_POS_X, DEFAULT_START_POS_Y);
- // Focus the content so the keyboard can be used.
- this.win.focus();
-
return true;
},
/**
* Hide the eye-dropper highlighter.
*/
hide() {
if (this.highlighterEnv.isXUL) {
@@ -190,30 +191,31 @@ EyeDropper.prototype = {
this.getElement("root").setAttribute("hidden", "true");
this.getElement("root").removeAttribute("drawn");
this.emit("hidden");
},
prepareImageCapture() {
// Get the image data from the content window.
- let imageData = getWindowAsImageData(this.win);
+ getWindowAsImageData(this.win)
+ .then(imageData => this.win.createImageBitmap(imageData))
- // We need to transform imageData to something drawWindow will consume. An ImageBitmap
- // works well. We could have used an Image, but doing so results in errors if the page
- // defines CSP headers.
- this.win.createImageBitmap(imageData).then(image => {
- this.pageImage = image;
- // We likely haven't drawn anything yet (no mousemove events yet), so start now.
- this.draw();
+ // We need to transform imageData to something drawWindow will consume. An
+ // ImageBitmap works well. We could have used an Image, but doing so results
+ // in errors if the page defines CSP headers.
+ .then(image => {
+ this.pageImage = image;
+ // We likely haven't drawn anything yet (no mousemove events yet), so start now.
+ this.draw();
- // Set an attribute on the root element to be able to run tests after the first draw
- // was done.
- this.getElement("root").setAttribute("drawn", "true");
- });
+ // Set an attribute on the root element to be able to run tests after the
+ // first draw was done.
+ this.getElement("root").setAttribute("drawn", "true");
+ });
},
/**
* Get the number of cells (blown-up pixels) per direction in the grid.
*/
get cellsWide() {
// Canvas will render whole "pixels" (cells) only, and an even number at that. Round
// up to the nearest even number of pixels.
@@ -468,33 +470,37 @@ EyeDropper.prototype = {
}
};
exports.EyeDropper = EyeDropper;
/**
* Draw the visible portion of the window on a canvas and get the resulting ImageData.
* @param {Window} win
- * @return {ImageData} The image data for the window.
+ * @return {Promise} Resolves with the ImageData (after a run of the event loop to
+ * allow the window to draw the focus effects on a focused element).
*/
function getWindowAsImageData(win) {
let canvas = win.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
let scale = getCurrentZoom(win);
let width = win.innerWidth;
let height = win.innerHeight;
canvas.width = width * scale;
canvas.height = height * scale;
canvas.mozOpaque = true;
let ctx = canvas.getContext("2d");
+ ctx.scale(scale, scale);
- ctx.scale(scale, scale);
- ctx.drawWindow(win, win.scrollX, win.scrollY, width, height, "#fff");
-
- return ctx.getImageData(0, 0, canvas.width, canvas.height);
+ return new Promise(resolve => {
+ setTimeout(() => {
+ ctx.drawWindow(win, win.scrollX, win.scrollY, width, height, "#fff");
+ resolve(ctx.getImageData(0, 0, canvas.width, canvas.height));
+ }, 0);
+ });
}
/**
* Get a formatted CSS color string from a color value.
* @param {array} rgb Rgb values of a color to format.
* @param {string} format Format of string. One of "hex", "rgb", "hsl", "name".
* @return {string} Formatted color value, e.g. "#FFF" or "hsl(20, 10%, 10%)".
*/