diff options
-rw-r--r-- | application/palemoon/base/content/browser-fullZoom.js | 210 |
1 files changed, 93 insertions, 117 deletions
diff --git a/application/palemoon/base/content/browser-fullZoom.js b/application/palemoon/base/content/browser-fullZoom.js index 0837bf7c2..890cd8440 100644 --- a/application/palemoon/base/content/browser-fullZoom.js +++ b/application/palemoon/base/content/browser-fullZoom.js @@ -1,14 +1,6 @@ -/* -#ifdef 0 - * This Source Code Form is subject to the terms of the Mozilla Public +/* 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/. -#endif - */ - -// One of the possible values for the mousewheel.* preferences. -// From nsEventStateManager.cpp. -const MOUSE_SCROLL_ZOOM = 3; + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * Controls the "full zoom" setting and its site-specific preferences. @@ -36,7 +28,6 @@ var FullZoom = { return this._siteSpecificPref; }, - //**************************************************************************// // nsISupports QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener, @@ -45,12 +36,10 @@ var FullZoom = { Ci.nsISupportsWeakReference, Ci.nsISupports]), - //**************************************************************************// // Initialization & Destruction init: function FullZoom_init() { - // Listen for scrollwheel events so we can save scrollwheel-based changes. - window.addEventListener("DOMMouseScroll", this, false); + gBrowser.addEventListener("ZoomChangeUsingMouseWheel", this); // Register ourselves with the service so we know when our pref changes. this._cps2 = Cc["@mozilla.org/content-pref/service;1"]. @@ -74,76 +63,30 @@ var FullZoom = { } // This should be nulled after initialization. - this._initialLocations.clear(); this._initialLocations = null; }, destroy: function FullZoom_destroy() { gPrefService.removeObserver("browser.zoom.", this); this._cps2.removeObserverForName(this.name, this); - window.removeEventListener("DOMMouseScroll", this, false); + gBrowser.removeEventListener("ZoomChangeUsingMouseWheel", this); }, - //**************************************************************************// // Event Handlers // nsIDOMEventListener handleEvent: function FullZoom_handleEvent(event) { switch (event.type) { - case "DOMMouseScroll": - this._handleMouseScrolled(event); + case "ZoomChangeUsingMouseWheel": + let browser = this._getTargetedBrowser(event); + this._ignorePendingZoomAccesses(browser); + this._applyZoomToPref(browser); break; } }, - _handleMouseScrolled: function FullZoom__handleMouseScrolled(event) { - // Construct the "mousewheel action" pref key corresponding to this event. - // Based on nsEventStateManager::WheelPrefs::GetBasePrefName(). - var pref = "mousewheel."; - - var pressedModifierCount = event.shiftKey + event.ctrlKey + event.altKey + - event.metaKey + event.getModifierState("OS"); - if (pressedModifierCount != 1) { - pref += "default."; - } else if (event.shiftKey) { - pref += "with_shift."; - } else if (event.ctrlKey) { - pref += "with_control."; - } else if (event.altKey) { - pref += "with_alt."; - } else if (event.metaKey) { - pref += "with_meta."; - } else { - pref += "with_win."; - } - - pref += "action"; - - // Don't do anything if this isn't a "zoom" scroll event. - var isZoomEvent = false; - try { - isZoomEvent = (gPrefService.getIntPref(pref) == MOUSE_SCROLL_ZOOM); - } catch (e) {} - if (!isZoomEvent) - return; - - // XXX Lazily cache all the possible action prefs so we don't have to get - // them anew from the pref service for every scroll event? We'd have to - // make sure to observe them so we can update the cache when they change. - - // We have to call _applyZoomToPref in a timeout because we handle the - // event before the event state manager has a chance to apply the zoom - // during nsEventStateManager::PostHandleEvent. - let browser = gBrowser.selectedBrowser; - let token = this._getBrowserToken(browser); - window.setTimeout(function () { - if (token.isCurrent) - this._applyZoomToPref(browser); - }.bind(this), 0); - }, - // nsIObserver observe: function (aSubject, aTopic, aData) { @@ -165,12 +108,12 @@ var FullZoom = { // nsIContentPrefObserver - onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) { - this._onContentPrefChanged(aGroup, aValue); + onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue, aIsPrivate) { + this._onContentPrefChanged(aGroup, aValue, aIsPrivate); }, - onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) { - this._onContentPrefChanged(aGroup, undefined); + onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName, aIsPrivate) { + this._onContentPrefChanged(aGroup, undefined, aIsPrivate); }, /** @@ -181,7 +124,7 @@ var FullZoom = { * @param aValue The new value of the changed preference. Pass undefined to * indicate the preference's removal. */ - _onContentPrefChanged: function FullZoom__onContentPrefChanged(aGroup, aValue) { + _onContentPrefChanged: function FullZoom__onContentPrefChanged(aGroup, aValue, aIsPrivate) { if (this._isNextContentPrefChangeInternal) { // Ignore changes that FullZoom itself makes. This works because the // content pref service calls callbacks before notifying observers, and it @@ -194,9 +137,10 @@ var FullZoom = { if (!browser.currentURI) return; + let ctxt = this._loadContextFromBrowser(browser); let domain = this._cps2.extractDomain(browser.currentURI.spec); if (aGroup) { - if (aGroup == domain) + if (aGroup == domain && ctxt.usePrivateBrowsing == aIsPrivate) this._applyPrefToZoom(aValue, browser); return; } @@ -208,10 +152,9 @@ var FullZoom = { // zoom should be set to the new global preference now that the global // preference has changed. let hasPref = false; - let ctxt = this._loadContextFromBrowser(browser); let token = this._getBrowserToken(browser); this._cps2.getByDomainAndName(browser.currentURI.spec, this.name, ctxt, { - handleResult: function () hasPref = true, + handleResult: function () { hasPref = true; }, handleCompletion: function () { if (!hasPref && token.isCurrent) this._applyPrefToZoom(undefined, browser); @@ -234,6 +177,7 @@ var FullZoom = { */ onLocationChange: function FullZoom_onLocationChange(aURI, aIsTabSwitch, aBrowser) { let browser = aBrowser || gBrowser.selectedBrowser; + // If we haven't been initialized yet but receive an onLocationChange // notification then let's store and replay it upon initialization. if (this._initialLocations) { @@ -247,14 +191,14 @@ var FullZoom = { this._ignorePendingZoomAccesses(browser); if (!aURI || (aIsTabSwitch && !this.siteSpecific)) { - this._notifyOnLocationChange(); + this._notifyOnLocationChange(browser); return; } // Avoid the cps roundtrip and apply the default/global pref. if (aURI.spec == "about:blank") { this._applyPrefToZoom(undefined, browser, - this._notifyOnLocationChange.bind(this)); + this._notifyOnLocationChange.bind(this, browser)); return; } @@ -262,7 +206,7 @@ var FullZoom = { if (!aIsTabSwitch && browser.isSyntheticDocument) { ZoomManager.setZoomForBrowser(browser, 1); // _ignorePendingZoomAccesses already called above, so no need here. - this._notifyOnLocationChange(); + this._notifyOnLocationChange(browser); return; } @@ -271,7 +215,7 @@ var FullZoom = { let pref = this._cps2.getCachedByDomainAndName(aURI.spec, this.name, ctxt); if (pref) { this._applyPrefToZoom(pref.value, browser, - this._notifyOnLocationChange.bind(this)); + this._notifyOnLocationChange.bind(this, browser)); return; } @@ -279,14 +223,14 @@ var FullZoom = { let value = undefined; let token = this._getBrowserToken(browser); this._cps2.getByDomainAndName(aURI.spec, this.name, ctxt, { - handleResult: function (resultPref) value = resultPref.value, + handleResult: function (resultPref) { value = resultPref.value; }, handleCompletion: function () { if (!token.isCurrent) { - this._notifyOnLocationChange(); + this._notifyOnLocationChange(browser); return; } this._applyPrefToZoom(value, browser, - this._notifyOnLocationChange.bind(this)); + this._notifyOnLocationChange.bind(this, browser)); }.bind(this) }); }, @@ -299,7 +243,6 @@ var FullZoom = { menuItem.setAttribute("checked", !ZoomManager.useFullZoom); }, - //**************************************************************************// // Setting & Pref Manipulation /** @@ -323,19 +266,32 @@ var FullZoom = { }, /** - * Sets the zoom level of the page in the current browser to the global zoom + * Sets the zoom level for the given browser to the given floating + * point value, where 1 is the default zoom level. + */ + setZoom: function (value, browser = gBrowser.selectedBrowser) { + ZoomManager.setZoomForBrowser(browser, value); + this._ignorePendingZoomAccesses(browser); + this._applyZoomToPref(browser); + }, + + /** + * Sets the zoom level of the page in the given browser to the global zoom * level. + * + * @return A promise which resolves when the zoom reset has been applied. */ - reset: function FullZoom_reset() { - let browser = gBrowser.selectedBrowser; + reset: function FullZoom_reset(browser = gBrowser.selectedBrowser) { let token = this._getBrowserToken(browser); - this._getGlobalValue(browser, function (value) { + let result = this._getGlobalValue(browser).then(value => { if (token.isCurrent) { ZoomManager.setZoomForBrowser(browser, value === undefined ? 1 : value); this._ignorePendingZoomAccesses(browser); + Services.obs.notifyObservers(browser, "browser-fullZoom:zoomReset", ""); } }); this._removePref(browser); + return result; }, /** @@ -383,7 +339,7 @@ var FullZoom = { } let token = this._getBrowserToken(aBrowser); - this._getGlobalValue(aBrowser, function (value) { + this._getGlobalValue(aBrowser).then(value => { if (token.isCurrent) { ZoomManager.setZoomForBrowser(aBrowser, value === undefined ? 1 : value); this._ignorePendingZoomAccesses(aBrowser); @@ -399,6 +355,7 @@ var FullZoom = { * @param browser The zoom of this browser will be saved. Required. */ _applyZoomToPref: function FullZoom__applyZoomToPref(browser) { + Services.obs.notifyObservers(browser, "browser-fullZoom:zoomChange", ""); if (!this.siteSpecific || gInPrintPreviewMode || browser.isSyntheticDocument) @@ -419,6 +376,7 @@ var FullZoom = { * @param browser The zoom of this browser will be removed. Required. */ _removePref: function FullZoom__removePref(browser) { + Services.obs.notifyObservers(browser, "browser-fullZoom:zoomReset", ""); if (browser.isSyntheticDocument) return; let ctxt = this._loadContextFromBrowser(browser); @@ -429,7 +387,6 @@ var FullZoom = { }); }, - //**************************************************************************// // Utilities /** @@ -462,6 +419,30 @@ var FullZoom = { }, /** + * Returns the browser that the supplied zoom event is associated with. + * @param event The ZoomChangeUsingMouseWheel event. + * @return The associated browser element, if one exists, otherwise null. + */ + _getTargetedBrowser: function FullZoom__getTargetedBrowser(event) { + let target = event.originalTarget; + + // With remote content browsers, the event's target is the browser + // we're looking for. + const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + if (target instanceof window.XULElement && + target.localName == "browser" && + target.namespaceURI == XUL_NS) + return target; + + // With in-process content browsers, the event's target is the content + // document. + if (target.nodeType == Node.DOCUMENT_NODE) + return gBrowser.getBrowserForDocument(target); + + throw new Error("Unexpected ZoomChangeUsingMouseWheel event source"); + }, + + /** * Increments the zoom change token for the given browser so that pending * async operations know that it may be unsafe to access they zoom when they * finish. @@ -491,54 +472,49 @@ var FullZoom = { /** * Gets the global browser.content.full-zoom content preference. * - * WARNING: callback may be called synchronously or asynchronously. The - * reason is that it's usually desirable to avoid turns of the event loop - * where possible, since they can lead to visible, jarring jumps in zoom - * level. It's not always possible to avoid them, though. As a convenience, - * then, this method takes a callback and returns nothing. - * - * @param browser The content browser pertaining to the zoom. - * @param callback Synchronously or asynchronously called when done. It's - * bound to this object (FullZoom) and called as: - * callback(prefValue) + * @param browser The browser pertaining to the zoom. + * @returns Promise<prefValue> + * Resolves to the preference value when done. */ - _getGlobalValue: function FullZoom__getGlobalValue(browser, callback) { + _getGlobalValue: function FullZoom__getGlobalValue(browser) { // * !("_globalValue" in this) => global value not yet cached. // * this._globalValue === undefined => global value known not to exist. // * Otherwise, this._globalValue is a number, the global value. - if ("_globalValue" in this) { - callback.call(this, this._globalValue, true); - return; - } - let value = undefined; - this._cps2.getGlobal(this.name, this._loadContextFromBrowser(browser), { - handleResult: function (pref) value = pref.value, - handleCompletion: function (reason) { - this._globalValue = this._ensureValid(value); - callback.call(this, this._globalValue); - }.bind(this) + return new Promise(resolve => { + if ("_globalValue" in this) { + resolve(this._globalValue); + return; + } + let value = undefined; + this._cps2.getGlobal(this.name, this._loadContextFromBrowser(browser), { + handleResult: function (pref) { value = pref.value; }, + handleCompletion: (reason) => { + this._globalValue = this._ensureValid(value); + resolve(this._globalValue); + } + }); }); }, /** - * Gets the load context from the given content browser. + * Gets the load context from the given Browser. * * @param Browser The Browser whose load context will be returned. - * @return The nsILoadContext of the given Browser. + * @return The nsILoadContext of the given Browser. */ _loadContextFromBrowser: function FullZoom__loadContextFromBrowser(browser) { return browser.loadContext; }, /** - * Asynchronously broadcasts a "browser-fullZoom:locationChange" notification - * so that tests can select tabs, load pages, etc. and be notified when the - * zoom levels on those pages change. The notification is always asynchronous - * so that observers are guaranteed a consistent behavior. + * Asynchronously broadcasts "browser-fullZoom:location-change" so that + * listeners can be notified when the zoom levels on those pages change. + * The notification is always asynchronous so that observers are guaranteed a + * consistent behavior. */ - _notifyOnLocationChange: function FullZoom__notifyOnLocationChange() { + _notifyOnLocationChange: function FullZoom__notifyOnLocationChange(browser) { this._executeSoon(function () { - Services.obs.notifyObservers(null, "browser-fullZoom:locationChange", ""); + Services.obs.notifyObservers(browser, "browser-fullZoom:location-change", ""); }); }, |