зеркало из https://github.com/mozilla/pjs.git
378 строки
13 KiB
JavaScript
378 строки
13 KiB
JavaScript
/*
|
|
#ifdef 0
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is Content Preferences (cpref).
|
|
*
|
|
* The Initial Developer of the Original Code is Mozilla.
|
|
* Portions created by the Initial Developer are Copyright (C) 2006
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Myk Melez <myk@mozilla.org>
|
|
* Dão Gottwald <dao@mozilla.com>
|
|
* Ehsan Akhgari <ehsan.akhgari@gmail.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK *****
|
|
#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 = {
|
|
|
|
//**************************************************************************//
|
|
// Name & Values
|
|
|
|
// The name of the setting. Identifies the setting in the 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 FullZoom_get_globalValue() {
|
|
var globalValue = this._cps.getPref(null, this.name);
|
|
if (typeof globalValue != "undefined")
|
|
globalValue = this._ensureValid(globalValue);
|
|
delete this.globalValue;
|
|
return this.globalValue = globalValue;
|
|
},
|
|
|
|
|
|
//**************************************************************************//
|
|
// Convenience Getters
|
|
|
|
// Content Pref Service
|
|
get _cps FullZoom_get__cps() {
|
|
delete this._cps;
|
|
return this._cps = Cc["@mozilla.org/content-pref/service;1"].
|
|
getService(Ci.nsIContentPrefService);
|
|
},
|
|
|
|
get _prefBranch FullZoom_get__prefBranch() {
|
|
delete this._prefBranch;
|
|
return this._prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
|
getService(Ci.nsIPrefBranch2);
|
|
},
|
|
|
|
// browser.zoom.siteSpecific preference cache
|
|
_siteSpecificPref: undefined,
|
|
|
|
// browser.zoom.updateBackgroundTabs preference cache
|
|
updateBackgroundTabs: undefined,
|
|
|
|
// whether we are in private browsing mode
|
|
_inPrivateBrowsing: false,
|
|
|
|
get siteSpecific FullZoom_get_siteSpecific() {
|
|
return !this._inPrivateBrowsing && this._siteSpecificPref;
|
|
},
|
|
|
|
//**************************************************************************//
|
|
// nsISupports
|
|
|
|
// We can't use the Ci shortcut here because it isn't defined yet.
|
|
interfaces: [Components.interfaces.nsIDOMEventListener,
|
|
Components.interfaces.nsIObserver,
|
|
Components.interfaces.nsIContentPrefObserver,
|
|
Components.interfaces.nsISupportsWeakReference,
|
|
Components.interfaces.nsISupports],
|
|
|
|
QueryInterface: function FullZoom_QueryInterface(aIID) {
|
|
if (!this.interfaces.some(function (v) aIID.equals(v)))
|
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
|
return this;
|
|
},
|
|
|
|
|
|
//**************************************************************************//
|
|
// 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.
|
|
this._cps.addObserver(this.name, this);
|
|
|
|
// We disable site-specific preferences in Private Browsing mode, because the
|
|
// content preferences module is disabled
|
|
let os = Cc["@mozilla.org/observer-service;1"].
|
|
getService(Ci.nsIObserverService);
|
|
os.addObserver(this, "private-browsing", true);
|
|
|
|
// Retrieve the initial status of the Private Browsing mode.
|
|
this._inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
|
|
getService(Ci.nsIPrivateBrowsingService).
|
|
privateBrowsingEnabled;
|
|
|
|
this._siteSpecificPref =
|
|
this._prefBranch.getBoolPref("browser.zoom.siteSpecific");
|
|
this.updateBackgroundTabs =
|
|
this._prefBranch.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.
|
|
this._prefBranch.addObserver("browser.zoom.", this, true);
|
|
},
|
|
|
|
destroy: function FullZoom_destroy() {
|
|
let os = Cc["@mozilla.org/observer-service;1"].
|
|
getService(Ci.nsIObserverService);
|
|
os.removeObserver(this, "private-browsing");
|
|
this._prefBranch.removeObserver("browser.zoom.", this);
|
|
this._cps.removeObserver(this.name, this);
|
|
window.removeEventListener("DOMMouseScroll", this, false);
|
|
delete this._cps;
|
|
},
|
|
|
|
|
|
//**************************************************************************//
|
|
// 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 =
|
|
this._prefBranch.getBoolPref("browser.zoom.siteSpecific");
|
|
break;
|
|
case "browser.zoom.updateBackgroundTabs":
|
|
this.updateBackgroundTabs =
|
|
this._prefBranch.getBoolPref("browser.zoom.updateBackgroundTabs");
|
|
break;
|
|
}
|
|
break;
|
|
case "private-browsing":
|
|
switch (aData) {
|
|
case "enter":
|
|
this._inPrivateBrowsing = true;
|
|
break;
|
|
case "exit":
|
|
this._inPrivateBrowsing = false;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
},
|
|
|
|
// nsIContentPrefObserver
|
|
|
|
onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) {
|
|
if (aGroup == this._cps.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 (!this._cps.hasPref(gBrowser.currentURI, this.name))
|
|
this._applyPrefToSetting();
|
|
}
|
|
},
|
|
|
|
onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) {
|
|
if (aGroup == this._cps.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 (!this._cps.hasPref(gBrowser.currentURI, this.name))
|
|
this._applyPrefToSetting();
|
|
}
|
|
},
|
|
|
|
// location change observer
|
|
|
|
onLocationChange: function FullZoom_onLocationChange(aURI, aBrowser) {
|
|
if (!aURI)
|
|
return;
|
|
this._applyPrefToSetting(this._cps.getPref(aURI, this.name), aBrowser);
|
|
},
|
|
|
|
// 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();
|
|
},
|
|
|
|
setSettingValue: function FullZoom_setSettingValue() {
|
|
var value = this._cps.getPref(gBrowser.currentURI, this.name);
|
|
this._applyPrefToSetting(value);
|
|
},
|
|
|
|
/**
|
|
* 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) {
|
|
var browser = aBrowser || gBrowser.selectedBrowser;
|
|
|
|
if (!this.siteSpecific || gInPrintPreviewMode ||
|
|
browser.contentDocument instanceof Ci.nsIImageDocument)
|
|
return;
|
|
|
|
try {
|
|
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 instanceof Ci.nsIImageDocument)
|
|
return;
|
|
|
|
var zoomLevel = ZoomManager.zoom;
|
|
this._cps.setPref(gBrowser.currentURI, this.name, zoomLevel);
|
|
},
|
|
|
|
_removePref: function FullZoom__removePref() {
|
|
if (!(content.document instanceof Ci.nsIImageDocument))
|
|
this._cps.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;
|
|
}
|
|
};
|