setDesktopBackground.js (8955B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* import-globals-from /browser/base/content/utilityOverlay.js */ 6 7 var gSetBackground = { 8 _position: AppConstants.platform == "macosx" ? "STRETCH" : "", 9 _backgroundColor: AppConstants.platform != "macosx" ? 0 : undefined, 10 _screenWidth: 0, 11 _screenHeight: 0, 12 _image: null, 13 _canvas: null, 14 _imageName: null, 15 16 get _shell() { 17 return Cc["@mozilla.org/browser/shell-service;1"].getService( 18 Ci.nsIShellService 19 ); 20 }, 21 22 load() { 23 this._canvas = document.getElementById("screen"); 24 this._screenWidth = screen.width; 25 this._screenHeight = screen.height; 26 // Cap ratio to 4 so the dialog width doesn't get ridiculous. Highest 27 // regular screens seem to be 32:9 (3.56) according to Wikipedia. 28 let screenRatio = Math.min(this._screenWidth / this._screenHeight, 4); 29 this._canvas.width = this._canvas.height * screenRatio; 30 document.getElementById("preview-unavailable").style.width = 31 this._canvas.width + "px"; 32 33 if (AppConstants.platform == "macosx") { 34 document 35 .getElementById("SetDesktopBackgroundDialog") 36 .getButton("accept").hidden = true; 37 38 document 39 .getElementById("setDesktopBackground") 40 .addEventListener("command", () => this.setDesktopBackground()); 41 42 document 43 .getElementById("showDesktopPreferences") 44 .addEventListener("command", () => { 45 this._shell 46 .QueryInterface(Ci.nsIMacShellService) 47 .showDesktopPreferences(); 48 }); 49 } else { 50 let multiMonitors = false; 51 if (AppConstants.platform == "linux") { 52 // getMonitors only ever returns the primary monitor on Linux, so just 53 // always show the option 54 multiMonitors = true; 55 } else { 56 const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); 57 const monitors = gfxInfo.getMonitors(); 58 multiMonitors = monitors.length > 1; 59 } 60 61 if (!multiMonitors) { 62 // Hide span option on single monitor systems. 63 document.getElementById("spanPosition").hidden = true; 64 } 65 66 document 67 .getElementById("menuPosition") 68 .addEventListener("command", () => this.updatePosition()); 69 document 70 .getElementById("desktopColor") 71 .addEventListener("change", event => 72 this.updateColor(event.currentTarget.value) 73 ); 74 } 75 76 document.addEventListener("dialogaccept", function () { 77 gSetBackground.setDesktopBackground(); 78 }); 79 // make sure that the correct dimensions will be used 80 setTimeout( 81 function (self) { 82 self.init(window.arguments[0], window.arguments[1]); 83 }, 84 0, 85 this 86 ); 87 }, 88 89 init(aImage, aImageName) { 90 this._image = aImage; 91 this._imageName = aImageName; 92 93 // set the size of the coordinate space 94 this._canvas.width = this._canvas.clientWidth; 95 this._canvas.height = this._canvas.clientHeight; 96 97 var ctx = this._canvas.getContext("2d"); 98 ctx.scale( 99 this._canvas.clientWidth / this._screenWidth, 100 this._canvas.clientHeight / this._screenHeight 101 ); 102 103 if (AppConstants.platform != "macosx") { 104 this._initColor(); 105 } else { 106 // Make sure to reset the button state in case the user has already 107 // set an image as their desktop background. 108 var setDesktopBackground = document.getElementById( 109 "setDesktopBackground" 110 ); 111 setDesktopBackground.hidden = false; 112 document.l10n.setAttributes( 113 setDesktopBackground, 114 "set-desktop-background-accept" 115 ); 116 setDesktopBackground.disabled = false; 117 118 document.getElementById("showDesktopPreferences").hidden = true; 119 } 120 this.updatePosition(); 121 }, 122 123 setDesktopBackground() { 124 if (AppConstants.platform != "macosx") { 125 Services.xulStore.persist( 126 document.getElementById("menuPosition"), 127 "value" 128 ); 129 this._shell.desktopBackgroundColor = this._hexStringToLong( 130 this._backgroundColor 131 ); 132 } else { 133 Services.obs.addObserver(this, "shell:desktop-background-changed"); 134 135 var setDesktopBackground = document.getElementById( 136 "setDesktopBackground" 137 ); 138 setDesktopBackground.disabled = true; 139 document.l10n.setAttributes( 140 setDesktopBackground, 141 "set-desktop-background-downloading" 142 ); 143 } 144 this._shell.setDesktopBackground( 145 this._image, 146 Ci.nsIShellService["BACKGROUND_" + this._position], 147 this._imageName 148 ); 149 }, 150 151 updatePosition() { 152 var ctx = this._canvas.getContext("2d"); 153 ctx.clearRect(0, 0, this._screenWidth, this._screenHeight); 154 document.getElementById("preview-unavailable").hidden = true; 155 156 if (AppConstants.platform != "macosx") { 157 this._position = document.getElementById("menuPosition").value; 158 } 159 160 switch (this._position) { 161 case "TILE": 162 ctx.save(); 163 ctx.fillStyle = ctx.createPattern(this._image, "repeat"); 164 ctx.fillRect(0, 0, this._screenWidth, this._screenHeight); 165 ctx.restore(); 166 break; 167 case "STRETCH": 168 ctx.drawImage(this._image, 0, 0, this._screenWidth, this._screenHeight); 169 break; 170 case "CENTER": { 171 let x = (this._screenWidth - this._image.naturalWidth) / 2; 172 let y = (this._screenHeight - this._image.naturalHeight) / 2; 173 ctx.drawImage(this._image, x, y); 174 break; 175 } 176 case "FILL": { 177 // Try maxing width first, overflow height. 178 let widthRatio = this._screenWidth / this._image.naturalWidth; 179 let width = this._image.naturalWidth * widthRatio; 180 let height = this._image.naturalHeight * widthRatio; 181 if (height < this._screenHeight) { 182 // Height less than screen, max height and overflow width. 183 let heightRatio = this._screenHeight / this._image.naturalHeight; 184 width = this._image.naturalWidth * heightRatio; 185 height = this._image.naturalHeight * heightRatio; 186 } 187 let x = (this._screenWidth - width) / 2; 188 let y = (this._screenHeight - height) / 2; 189 ctx.drawImage(this._image, x, y, width, height); 190 break; 191 } 192 case "FIT": { 193 // Try maxing width first, top and bottom borders. 194 let widthRatio = this._screenWidth / this._image.naturalWidth; 195 let width = this._image.naturalWidth * widthRatio; 196 let height = this._image.naturalHeight * widthRatio; 197 let x = 0; 198 let y = (this._screenHeight - height) / 2; 199 if (height > this._screenHeight) { 200 // Height overflow, maximise height, side borders. 201 let heightRatio = this._screenHeight / this._image.naturalHeight; 202 width = this._image.naturalWidth * heightRatio; 203 height = this._image.naturalHeight * heightRatio; 204 x = (this._screenWidth - width) / 2; 205 y = 0; 206 } 207 ctx.drawImage(this._image, x, y, width, height); 208 break; 209 } 210 case "SPAN": { 211 document.getElementById("preview-unavailable").hidden = false; 212 ctx.fillStyle = "#222"; 213 ctx.fillRect(0, 0, this._screenWidth, this._screenHeight); 214 ctx.stroke(); 215 } 216 } 217 }, 218 }; 219 220 if (AppConstants.platform != "macosx") { 221 gSetBackground._initColor = function () { 222 var color = this._shell.desktopBackgroundColor; 223 224 const rMask = 4294901760; 225 const gMask = 65280; 226 const bMask = 255; 227 var r = (color & rMask) >> 16; 228 var g = (color & gMask) >> 8; 229 var b = color & bMask; 230 this.updateColor(this._rgbToHex(r, g, b)); 231 232 var colorpicker = document.getElementById("desktopColor"); 233 colorpicker.value = this._backgroundColor; 234 }; 235 236 gSetBackground.updateColor = function (aColor) { 237 this._backgroundColor = aColor; 238 this._canvas.style.backgroundColor = aColor; 239 }; 240 241 // Converts a color string in the format "#RRGGBB" to an integer. 242 gSetBackground._hexStringToLong = function (aString) { 243 return ( 244 (parseInt(aString.substring(1, 3), 16) << 16) | 245 (parseInt(aString.substring(3, 5), 16) << 8) | 246 parseInt(aString.substring(5, 7), 16) 247 ); 248 }; 249 250 gSetBackground._rgbToHex = function (aR, aG, aB) { 251 return ( 252 "#" + 253 [aR, aG, aB] 254 .map(aInt => aInt.toString(16).replace(/^(.)$/, "0$1")) 255 .join("") 256 .toUpperCase() 257 ); 258 }; 259 } else { 260 gSetBackground.observe = function (aSubject, aTopic) { 261 if (aTopic == "shell:desktop-background-changed") { 262 document.getElementById("setDesktopBackground").hidden = true; 263 document.getElementById("showDesktopPreferences").hidden = false; 264 265 Services.obs.removeObserver(this, "shell:desktop-background-changed"); 266 } 267 }; 268 } 269 270 window.addEventListener("load", () => gSetBackground.load());