mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
337 lines
12 KiB
JavaScript
337 lines
12 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;
|
|
|
|
Cu.import('resource://gre/modules/ContentPrefInstance.jsm');
|
|
|
|
function getContentPrefs(aWindow) {
|
|
let context = aWindow ? aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
.getInterface(Ci.nsIWebNavigation)
|
|
.QueryInterface(Ci.nsILoadContext) : null;
|
|
return new ContentPrefInstance(context);
|
|
}
|
|
|
|
/**
|
|
* 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 = getContentPrefs(gBrowser.contentDocument.defaultView).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.
|
|
getContentPrefs().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);
|
|
getContentPrefs().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::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 _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) {
|
|
let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView);
|
|
if (aGroup == 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 (!contentPrefs.hasPref(gBrowser.currentURI, this.name))
|
|
this._applyPrefToSetting();
|
|
}
|
|
},
|
|
|
|
onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) {
|
|
let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView);
|
|
if (aGroup == 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 (!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;
|
|
}
|
|
|
|
let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView);
|
|
if (contentPrefs.hasCachedPref(aURI, this.name)) {
|
|
let zoomValue = contentPrefs.getPref(aURI, this.name);
|
|
this._applyPrefToSetting(zoomValue, browser);
|
|
} else {
|
|
var self = this;
|
|
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 nsDocumentViewer::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 nsDocumentViewer::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;
|
|
getContentPrefs(gBrowser.contentDocument.defaultView).setPref(gBrowser.currentURI, this.name, zoomLevel);
|
|
},
|
|
|
|
_removePref: function FullZoom__removePref() {
|
|
if (!(content.document.mozSyntheticDocument))
|
|
getContentPrefs(gBrowser.contentDocument.defaultView).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;
|
|
}
|
|
};
|