зеркало из https://github.com/mozilla/pjs.git
322 строки
11 KiB
JavaScript
322 строки
11 KiB
JavaScript
/*
|
|
#ifdef 0
|
|
* 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;
|
|
|
|
/**
|
|
* Controls the "full zoom" setting and its site-specific preferences.
|
|
*/
|
|
var FullZoom = {
|
|
// Identifies the setting in the content prefs database.
|
|
name: "browser.content.full-zoom",
|
|
|
|
// The global value (if any) for the setting. Lazily loaded from the service
|
|
// when first requested, then updated by the pref change listener as it changes.
|
|
// If there is no global value, then this should be undefined.
|
|
get globalValue() {
|
|
var globalValue = Services.contentPrefs.getPref(null, this.name);
|
|
if (typeof globalValue != "undefined")
|
|
globalValue = this._ensureValid(globalValue);
|
|
delete this.globalValue;
|
|
return this.globalValue = globalValue;
|
|
},
|
|
|
|
// browser.zoom.siteSpecific preference cache
|
|
_siteSpecificPref: undefined,
|
|
|
|
// browser.zoom.updateBackgroundTabs preference cache
|
|
updateBackgroundTabs: undefined,
|
|
|
|
get siteSpecific() {
|
|
return this._siteSpecificPref;
|
|
},
|
|
|
|
//**************************************************************************//
|
|
// nsISupports
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener,
|
|
Ci.nsIObserver,
|
|
Ci.nsIContentPrefObserver,
|
|
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);
|
|
|
|
// Register ourselves with the service so we know when our pref changes.
|
|
Services.contentPrefs.addObserver(this.name, this);
|
|
|
|
this._siteSpecificPref =
|
|
gPrefService.getBoolPref("browser.zoom.siteSpecific");
|
|
this.updateBackgroundTabs =
|
|
gPrefService.getBoolPref("browser.zoom.updateBackgroundTabs");
|
|
// Listen for changes to the browser.zoom branch so we can enable/disable
|
|
// updating background tabs and per-site saving and restoring of zoom levels.
|
|
gPrefService.addObserver("browser.zoom.", this, true);
|
|
},
|
|
|
|
destroy: function FullZoom_destroy() {
|
|
gPrefService.removeObserver("browser.zoom.", this);
|
|
Services.contentPrefs.removeObserver(this.name, this);
|
|
window.removeEventListener("DOMMouseScroll", this, false);
|
|
},
|
|
|
|
|
|
//**************************************************************************//
|
|
// Event Handlers
|
|
|
|
// nsIDOMEventListener
|
|
|
|
handleEvent: function FullZoom_handleEvent(event) {
|
|
switch (event.type) {
|
|
case "DOMMouseScroll":
|
|
this._handleMouseScrolled(event);
|
|
break;
|
|
}
|
|
},
|
|
|
|
_handleMouseScrolled: function FullZoom__handleMouseScrolled(event) {
|
|
// Construct the "mousewheel action" pref key corresponding to this event.
|
|
// Based on nsEventStateManager::GetBasePrefKeyForMouseWheel.
|
|
var pref = "mousewheel";
|
|
if (event.axis == event.HORIZONTAL_AXIS)
|
|
pref += ".horizscroll";
|
|
|
|
if (event.shiftKey)
|
|
pref += ".withshiftkey";
|
|
else if (event.ctrlKey)
|
|
pref += ".withcontrolkey";
|
|
else if (event.altKey)
|
|
pref += ".withaltkey";
|
|
else if (event.metaKey)
|
|
pref += ".withmetakey";
|
|
else
|
|
pref += ".withnokey";
|
|
|
|
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 _applySettingToPref in a timeout because we handle
|
|
// the event before the event state manager has a chance to apply the zoom
|
|
// during nsEventStateManager::PostHandleEvent.
|
|
window.setTimeout(function (self) { self._applySettingToPref() }, 0, this);
|
|
},
|
|
|
|
// nsIObserver
|
|
|
|
observe: function (aSubject, aTopic, aData) {
|
|
switch (aTopic) {
|
|
case "nsPref:changed":
|
|
switch (aData) {
|
|
case "browser.zoom.siteSpecific":
|
|
this._siteSpecificPref =
|
|
gPrefService.getBoolPref("browser.zoom.siteSpecific");
|
|
break;
|
|
case "browser.zoom.updateBackgroundTabs":
|
|
this.updateBackgroundTabs =
|
|
gPrefService.getBoolPref("browser.zoom.updateBackgroundTabs");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
},
|
|
|
|
// nsIContentPrefObserver
|
|
|
|
onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) {
|
|
if (aGroup == Services.contentPrefs.grouper.group(gBrowser.currentURI))
|
|
this._applyPrefToSetting(aValue);
|
|
else if (aGroup == null) {
|
|
this.globalValue = this._ensureValid(aValue);
|
|
|
|
// If the current page doesn't have a site-specific preference,
|
|
// then its zoom should be set to the new global preference now that
|
|
// the global preference has changed.
|
|
if (!Services.contentPrefs.hasPref(gBrowser.currentURI, this.name))
|
|
this._applyPrefToSetting();
|
|
}
|
|
},
|
|
|
|
onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) {
|
|
if (aGroup == Services.contentPrefs.grouper.group(gBrowser.currentURI))
|
|
this._applyPrefToSetting();
|
|
else if (aGroup == null) {
|
|
this.globalValue = undefined;
|
|
|
|
// If the current page doesn't have a site-specific preference,
|
|
// then its zoom should be set to the default preference now that
|
|
// the global preference has changed.
|
|
if (!Services.contentPrefs.hasPref(gBrowser.currentURI, this.name))
|
|
this._applyPrefToSetting();
|
|
}
|
|
},
|
|
|
|
// location change observer
|
|
|
|
/**
|
|
* Called when the location of a tab changes.
|
|
* When that happens, we need to update the current zoom level if appropriate.
|
|
*
|
|
* @param aURI
|
|
* A URI object representing the new location.
|
|
* @param aIsTabSwitch
|
|
* Whether this location change has happened because of a tab switch.
|
|
* @param aBrowser
|
|
* (optional) browser object displaying the document
|
|
*/
|
|
onLocationChange: function FullZoom_onLocationChange(aURI, aIsTabSwitch, aBrowser) {
|
|
if (!aURI || (aIsTabSwitch && !this.siteSpecific))
|
|
return;
|
|
|
|
// Avoid the cps roundtrip and apply the default/global pref.
|
|
if (aURI.spec == "about:blank") {
|
|
this._applyPrefToSetting(undefined, aBrowser);
|
|
return;
|
|
}
|
|
|
|
let browser = aBrowser || gBrowser.selectedBrowser;
|
|
|
|
// Media documents should always start at 1, and are not affected by prefs.
|
|
if (!aIsTabSwitch && browser.contentDocument.mozSyntheticDocument) {
|
|
ZoomManager.setZoomForBrowser(browser, 1);
|
|
return;
|
|
}
|
|
|
|
if (Services.contentPrefs.hasCachedPref(aURI, this.name)) {
|
|
let zoomValue = Services.contentPrefs.getPref(aURI, this.name);
|
|
this._applyPrefToSetting(zoomValue, browser);
|
|
} else {
|
|
var self = this;
|
|
Services.contentPrefs.getPref(aURI, this.name, function (aResult) {
|
|
// Check that we're still where we expect to be in case this took a while.
|
|
// Null check currentURI, since the window may have been destroyed before
|
|
// we were called.
|
|
if (browser.currentURI && aURI.equals(browser.currentURI)) {
|
|
self._applyPrefToSetting(aResult, browser);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
// update state of zoom type menu item
|
|
|
|
updateMenu: function FullZoom_updateMenu() {
|
|
var menuItem = document.getElementById("toggle_zoom");
|
|
|
|
menuItem.setAttribute("checked", !ZoomManager.useFullZoom);
|
|
},
|
|
|
|
//**************************************************************************//
|
|
// Setting & Pref Manipulation
|
|
|
|
reduce: function FullZoom_reduce() {
|
|
ZoomManager.reduce();
|
|
this._applySettingToPref();
|
|
},
|
|
|
|
enlarge: function FullZoom_enlarge() {
|
|
ZoomManager.enlarge();
|
|
this._applySettingToPref();
|
|
},
|
|
|
|
reset: function FullZoom_reset() {
|
|
if (typeof this.globalValue != "undefined")
|
|
ZoomManager.zoom = this.globalValue;
|
|
else
|
|
ZoomManager.reset();
|
|
|
|
this._removePref();
|
|
},
|
|
|
|
/**
|
|
* Set the zoom level for the current tab.
|
|
*
|
|
* Per nsPresContext::setFullZoom, we can set the zoom to its current value
|
|
* without significant impact on performance, as the setting is only applied
|
|
* if it differs from the current setting. In fact getting the zoom and then
|
|
* checking ourselves if it differs costs more.
|
|
*
|
|
* And perhaps we should always set the zoom even if it was more expensive,
|
|
* since DocumentViewerImpl::SetTextZoom claims that child documents can have
|
|
* a different text zoom (although it would be unusual), and it implies that
|
|
* those child text zooms should get updated when the parent zoom gets set,
|
|
* and perhaps the same is true for full zoom
|
|
* (although DocumentViewerImpl::SetFullZoom doesn't mention it).
|
|
*
|
|
* So when we apply new zoom values to the browser, we simply set the zoom.
|
|
* We don't check first to see if the new value is the same as the current
|
|
* one.
|
|
**/
|
|
_applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue, aBrowser) {
|
|
if ((!this.siteSpecific) || gInPrintPreviewMode)
|
|
return;
|
|
|
|
var browser = aBrowser || (gBrowser && gBrowser.selectedBrowser);
|
|
try {
|
|
if (browser.contentDocument.mozSyntheticDocument)
|
|
return;
|
|
|
|
if (typeof aValue != "undefined")
|
|
ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue));
|
|
else if (typeof this.globalValue != "undefined")
|
|
ZoomManager.setZoomForBrowser(browser, this.globalValue);
|
|
else
|
|
ZoomManager.setZoomForBrowser(browser, 1);
|
|
}
|
|
catch(ex) {}
|
|
},
|
|
|
|
_applySettingToPref: function FullZoom__applySettingToPref() {
|
|
if (!this.siteSpecific || gInPrintPreviewMode ||
|
|
content.document.mozSyntheticDocument)
|
|
return;
|
|
|
|
var zoomLevel = ZoomManager.zoom;
|
|
Services.contentPrefs.setPref(gBrowser.currentURI, this.name, zoomLevel);
|
|
},
|
|
|
|
_removePref: function FullZoom__removePref() {
|
|
if (!(content.document.mozSyntheticDocument))
|
|
Services.contentPrefs.removePref(gBrowser.currentURI, this.name);
|
|
},
|
|
|
|
|
|
//**************************************************************************//
|
|
// Utilities
|
|
|
|
_ensureValid: function FullZoom__ensureValid(aValue) {
|
|
if (isNaN(aValue))
|
|
return 1;
|
|
|
|
if (aValue < ZoomManager.MIN)
|
|
return ZoomManager.MIN;
|
|
|
|
if (aValue > ZoomManager.MAX)
|
|
return ZoomManager.MAX;
|
|
|
|
return aValue;
|
|
}
|
|
};
|