fune/browser/components/shell/content/setDesktopBackground.js
Ian Moody 7d6860c063 Bug 612373 - Add "Span" option for Windows and Linux to "Set As Desktop Background". r=Gijs
Gnome introduced this in 2.30[0], Windows in 8[1].
Preview is just an "international prohibition symbol" to save the complicated
business of trying to calculate a semi-accurate one.

[0]
8eb0886312
https://bugzilla.gnome.org/show_bug.cgi?id=603551
[1]
https://superuser.com/questions/1061416/which-version-of-windows-introduced-the-span-wallpaper-style

Differential Revision: https://phabricator.services.mozilla.com/D23336

--HG--
extra : moz-landing-system : lando
2019-03-27 18:26:19 +00:00

223 lines
8.2 KiB
JavaScript

/* 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/. */
/* import-globals-from ../../../base/content/utilityOverlay.js */
var gSetBackground = {
_position: AppConstants.platform == "macosx" ? "STRETCH" : "",
_backgroundColor: AppConstants.platform != "macosx" ? 0 : undefined,
_screenWidth: 0,
_screenHeight: 0,
_image: null,
_canvas: null,
_imageName: null,
get _shell() {
return Cc["@mozilla.org/browser/shell-service;1"]
.getService(Ci.nsIShellService);
},
load() {
this._canvas = document.getElementById("screen");
this._screenWidth = screen.width;
this._screenHeight = screen.height;
// Cap ratio to 4 so the dialog width doesn't get ridiculous. Highest
// regular screens seem to be 32:9 (3.56) according to Wikipedia.
let screenRatio = Math.min(this._screenWidth / this._screenHeight, 4);
this._canvas.width = this._canvas.height * screenRatio;
if (AppConstants.platform == "macosx") {
document.documentElement.getButton("accept").hidden = true;
} else {
let multiMonitors = false;
try {
const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo);
const monitors = gfxInfo.getMonitors();
multiMonitors = monitors.length > 1;
} catch (e) {
// getMonitors() isn't implemented on Linux
multiMonitors = true;
}
if (!multiMonitors || AppConstants.isPlatformAndVersionAtMost("win", 6.1)) {
// Hide span option if < Win8 since that's when it was introduced.
document.getElementById("spanPosition").hidden = true;
}
}
document.addEventListener("dialogaccept", function() { gSetBackground.setDesktopBackground(); });
// make sure that the correct dimensions will be used
setTimeout(function(self) {
self.init(window.arguments[0], window.arguments[1]);
}, 0, this);
},
init(aImage, aImageName) {
this._image = aImage;
this._imageName = aImageName;
// set the size of the coordinate space
this._canvas.width = this._canvas.clientWidth;
this._canvas.height = this._canvas.clientHeight;
var ctx = this._canvas.getContext("2d");
ctx.scale(this._canvas.clientWidth / this._screenWidth, this._canvas.clientHeight / this._screenHeight);
if (AppConstants.platform != "macosx") {
this._initColor();
} else {
// Make sure to reset the button state in case the user has already
// set an image as their desktop background.
var setDesktopBackground = document.getElementById("setDesktopBackground");
setDesktopBackground.hidden = false;
var bundle = document.getElementById("backgroundBundle");
setDesktopBackground.label = bundle.getString("DesktopBackgroundSet");
setDesktopBackground.disabled = false;
document.getElementById("showDesktopPreferences").hidden = true;
}
this.updatePosition();
},
setDesktopBackground() {
if (AppConstants.platform != "macosx") {
Services.xulStore.persist(document.getElementById("menuPosition"), "value");
this._shell.desktopBackgroundColor = this._hexStringToLong(this._backgroundColor);
} else {
Services.obs.addObserver(this, "shell:desktop-background-changed");
var bundle = document.getElementById("backgroundBundle");
var setDesktopBackground = document.getElementById("setDesktopBackground");
setDesktopBackground.disabled = true;
setDesktopBackground.label = bundle.getString("DesktopBackgroundDownloading");
}
this._shell.setDesktopBackground(
this._image,
Ci.nsIShellService["BACKGROUND_" + this._position],
this._imageName);
},
updatePosition() {
var ctx = this._canvas.getContext("2d");
ctx.clearRect(0, 0, this._screenWidth, this._screenHeight);
if (AppConstants.platform != "macosx") {
this._position = document.getElementById("menuPosition").value;
}
switch (this._position) {
case "TILE":
ctx.save();
ctx.fillStyle = ctx.createPattern(this._image, "repeat");
ctx.fillRect(0, 0, this._screenWidth, this._screenHeight);
ctx.restore();
break;
case "STRETCH":
ctx.drawImage(this._image, 0, 0, this._screenWidth, this._screenHeight);
break;
case "CENTER": {
let x = (this._screenWidth - this._image.naturalWidth) / 2;
let y = (this._screenHeight - this._image.naturalHeight) / 2;
ctx.drawImage(this._image, x, y);
break;
}
case "FILL": {
// Try maxing width first, overflow height.
let widthRatio = this._screenWidth / this._image.naturalWidth;
let width = this._image.naturalWidth * widthRatio;
let height = this._image.naturalHeight * widthRatio;
if (height < this._screenHeight) {
// Height less than screen, max height and overflow width.
let heightRatio = this._screenHeight / this._image.naturalHeight;
width = this._image.naturalWidth * heightRatio;
height = this._image.naturalHeight * heightRatio;
}
let x = (this._screenWidth - width) / 2;
let y = (this._screenHeight - height) / 2;
ctx.drawImage(this._image, x, y, width, height);
break;
}
case "FIT": {
// Try maxing width first, top and bottom borders.
let widthRatio = this._screenWidth / this._image.naturalWidth;
let width = this._image.naturalWidth * widthRatio;
let height = this._image.naturalHeight * widthRatio;
let x = 0;
let y = (this._screenHeight - height) / 2;
if (height > this._screenHeight) {
// Height overflow, maximise height, side borders.
let heightRatio = this._screenHeight / this._image.naturalHeight;
width = this._image.naturalWidth * heightRatio;
height = this._image.naturalHeight * heightRatio;
x = (this._screenWidth - width) / 2;
y = 0;
}
ctx.drawImage(this._image, x, y, width, height);
break;
}
case "SPAN": {
ctx.fillStyle = "black";
ctx.fillRect(0, 0, this._screenWidth, this._screenHeight);
let x = this._screenWidth / 2;
let y = this._screenHeight / 2;
let radius = this._screenHeight * .4;
let delta = Math.sin(.25 * Math.PI) * radius; // opp = sin * hyp
ctx.lineWidth = radius / 4.5;
ctx.strokeStyle = "#9B2423";
ctx.arc(x, y, radius, -.75 * Math.PI, 1.25 * Math.PI);
ctx.stroke();
ctx.lineWidth *= .8;
ctx.lineTo(x + delta, y + delta);
ctx.stroke();
}
}
},
};
if (AppConstants.platform != "macosx") {
gSetBackground._initColor = function() {
var color = this._shell.desktopBackgroundColor;
const rMask = 4294901760;
const gMask = 65280;
const bMask = 255;
var r = (color & rMask) >> 16;
var g = (color & gMask) >> 8;
var b = (color & bMask);
this.updateColor(this._rgbToHex(r, g, b));
var colorpicker = document.getElementById("desktopColor");
colorpicker.value = this._backgroundColor;
};
gSetBackground.updateColor = function(aColor) {
this._backgroundColor = aColor;
this._canvas.style.backgroundColor = aColor;
};
// Converts a color string in the format "#RRGGBB" to an integer.
gSetBackground._hexStringToLong = function(aString) {
return parseInt(aString.substring(1, 3), 16) << 16 |
parseInt(aString.substring(3, 5), 16) << 8 |
parseInt(aString.substring(5, 7), 16);
};
gSetBackground._rgbToHex = function(aR, aG, aB) {
return "#" + [aR, aG, aB].map(aInt => aInt.toString(16).replace(/^(.)$/, "0$1"))
.join("").toUpperCase();
};
} else {
gSetBackground.observe = function(aSubject, aTopic, aData) {
if (aTopic == "shell:desktop-background-changed") {
document.getElementById("setDesktopBackground").hidden = true;
document.getElementById("showDesktopPreferences").hidden = false;
Services.obs.removeObserver(this, "shell:desktop-background-changed");
}
};
gSetBackground.showDesktopPrefs = function() {
this._shell.openApplication(Ci.nsIMacShellService.APPLICATION_DESKTOP);
};
}