[Mypal] Update browser-gestureSupport.

This commit is contained in:
Fedor 2020-09-09 17:30:12 +03:00
parent 73babd040e
commit d5885a6f81

View File

@ -25,11 +25,7 @@ var gGestureSupport = {
* True to add/init listeners and false to remove/uninit * True to add/init listeners and false to remove/uninit
*/ */
init: function(aAddListener) { init: function(aAddListener) {
// Bug 863514 - Make gesture support work in electrolysis const gestureEvents = ["SwipeGestureMayStart", "SwipeGestureStart",
if (gMultiProcessBrowser)
return;
const gestureEvents = ["SwipeGestureStart",
"SwipeGestureUpdate", "SwipeGestureEnd", "SwipeGesture", "SwipeGestureUpdate", "SwipeGestureEnd", "SwipeGesture",
"MagnifyGestureStart", "MagnifyGestureUpdate", "MagnifyGesture", "MagnifyGestureStart", "MagnifyGestureUpdate", "MagnifyGesture",
"RotateGestureStart", "RotateGestureUpdate", "RotateGesture", "RotateGestureStart", "RotateGestureUpdate", "RotateGesture",
@ -38,8 +34,9 @@ var gGestureSupport = {
let addRemove = aAddListener ? window.addEventListener : let addRemove = aAddListener ? window.addEventListener :
window.removeEventListener; window.removeEventListener;
gestureEvents.forEach(function(event) addRemove("Moz" + event, this, true), for (let event of gestureEvents) {
this); addRemove("Moz" + event, this, true);
}
}, },
/** /**
@ -57,13 +54,18 @@ var gGestureSupport = {
} }
// Create a preference object with some defaults // Create a preference object with some defaults
let def = function(aThreshold, aLatched) let def = (aThreshold, aLatched) =>
({ threshold: aThreshold, latched: !!aLatched }); ({ threshold: aThreshold, latched: !!aLatched });
switch (aEvent.type) { switch (aEvent.type) {
case "MozSwipeGestureMayStart":
if (this._shouldDoSwipeGesture(aEvent)) {
aEvent.preventDefault();
}
break;
case "MozSwipeGestureStart": case "MozSwipeGestureStart":
aEvent.preventDefault(); aEvent.preventDefault();
this._setupSwipeGesture(aEvent); this._setupSwipeGesture();
break; break;
case "MozSwipeGestureUpdate": case "MozSwipeGestureUpdate":
aEvent.preventDefault(); aEvent.preventDefault();
@ -175,14 +177,17 @@ var gGestureSupport = {
}, },
/** /**
* Sets up the history swipe animations for a swipe gesture event, if enabled. * Checks whether we want to start a swipe for aEvent and sets
* aEvent.allowedDirections to the right values.
* *
* @param aEvent * @param aEvent
* The swipe gesture start event. * The swipe gesture "MayStart" event.
* @return true if we're willing to start a swipe for this event, false
* otherwise.
*/ */
_setupSwipeGesture: function(aEvent) { _shouldDoSwipeGesture: function(aEvent) {
if (!this._swipeNavigatesHistory(aEvent)) if (!this._swipeNavigatesHistory(aEvent))
return; return false;
let canGoBack = gHistorySwipeAnimation.canGoBack(); let canGoBack = gHistorySwipeAnimation.canGoBack();
let canGoForward = gHistorySwipeAnimation.canGoForward(); let canGoForward = gHistorySwipeAnimation.canGoForward();
@ -195,7 +200,20 @@ var gGestureSupport = {
aEvent.allowedDirections |= isLTR ? aEvent.DIRECTION_RIGHT : aEvent.allowedDirections |= isLTR ? aEvent.DIRECTION_RIGHT :
aEvent.DIRECTION_LEFT; aEvent.DIRECTION_LEFT;
gHistorySwipeAnimation.startAnimation(); return true;
},
/**
* Sets up swipe gestures. This includes setting up swipe animations for the
* gesture, if enabled.
*
* @param aEvent
* The swipe gesture start event.
* @return true if swipe gestures could successfully be set up, false
* othwerwise.
*/
_setupSwipeGesture: function() {
gHistorySwipeAnimation.startAnimation(false);
this._doUpdate = function(aEvent) { this._doUpdate = function(aEvent) {
gHistorySwipeAnimation.updateAnimation(aEvent.delta); gHistorySwipeAnimation.updateAnimation(aEvent.delta);
@ -491,10 +509,6 @@ var gGestureSupport = {
* image * image
*/ */
restoreRotationState: function() { restoreRotationState: function() {
// Bug 863514 - Make gesture support work in electrolysis
if (gMultiProcessBrowser)
return;
if (!(content.document instanceof ImageDocument)) if (!(content.document instanceof ImageDocument))
return; return;
@ -546,8 +560,7 @@ var gHistorySwipeAnimation = {
return; return;
this.active = false; this.active = false;
this.isLTR = document.documentElement.mozMatchesSelector( this.isLTR = document.documentElement.matches(":-moz-locale-dir(ltr)");
":-moz-locale-dir(ltr)");
this._trackedSnapshots = []; this._trackedSnapshots = [];
this._historyIndex = -1; this._historyIndex = -1;
this._boxWidth = -1; this._boxWidth = -1;
@ -561,6 +574,7 @@ var gHistorySwipeAnimation = {
gBrowser.addEventListener("pagehide", this, false); gBrowser.addEventListener("pagehide", this, false);
gBrowser.addEventListener("pageshow", this, false); gBrowser.addEventListener("pageshow", this, false);
gBrowser.addEventListener("popstate", this, false); gBrowser.addEventListener("popstate", this, false);
gBrowser.addEventListener("DOMModalDialogClosed", this, false);
gBrowser.tabContainer.addEventListener("TabClose", this, false); gBrowser.tabContainer.addEventListener("TabClose", this, false);
} }
}, },
@ -572,6 +586,7 @@ var gHistorySwipeAnimation = {
gBrowser.removeEventListener("pagehide", this, false); gBrowser.removeEventListener("pagehide", this, false);
gBrowser.removeEventListener("pageshow", this, false); gBrowser.removeEventListener("pageshow", this, false);
gBrowser.removeEventListener("popstate", this, false); gBrowser.removeEventListener("popstate", this, false);
gBrowser.removeEventListener("DOMModalDialogClosed", this, false);
gBrowser.tabContainer.removeEventListener("TabClose", this, false); gBrowser.tabContainer.removeEventListener("TabClose", this, false);
this.active = false; this.active = false;
@ -609,6 +624,7 @@ var gHistorySwipeAnimation = {
*/ */
stopAnimation: function() { stopAnimation: function() {
gHistorySwipeAnimation._removeBoxes(); gHistorySwipeAnimation._removeBoxes();
this._historyIndex = gBrowser.webNavigation.sessionHistory.index;
}, },
/** /**
@ -643,7 +659,6 @@ var gHistorySwipeAnimation = {
else { else {
if (aVal < -1) if (aVal < -1)
aVal = -1; // Cap value to avoid sliding the page further than allowed. aVal = -1; // Cap value to avoid sliding the page further than allowed.
// The intention is to go forward. If there is a page to go forward to, // The intention is to go forward. If there is a page to go forward to,
// it should slide in from the right (LTR) or left (RTL). // it should slide in from the right (LTR) or left (RTL).
// Otherwise, the current page should slide to the left (LTR) or // Otherwise, the current page should slide to the left (LTR) or
@ -651,9 +666,10 @@ var gHistorySwipeAnimation = {
// For the backdrop to be visible in that case, the previous page needs // For the backdrop to be visible in that case, the previous page needs
// to be hidden (if it exists). // to be hidden (if it exists).
if (this._canGoForward) { if (this._canGoForward) {
this._nextBox.collapsed = false;
let offset = this.isLTR ? 1 : -1; let offset = this.isLTR ? 1 : -1;
this._positionBox(this._curBox, 0); this._positionBox(this._curBox, 0);
this._positionBox(this._nextBox, offset + aVal); // aVal is negative this._positionBox(this._nextBox, offset + aVal); // aval is negative
} }
else { else {
this._prevBox.collapsed = true; this._prevBox.collapsed = true;
@ -669,25 +685,34 @@ var gHistorySwipeAnimation = {
* An event to process. * An event to process.
*/ */
handleEvent: function(aEvent) { handleEvent: function(aEvent) {
let browser = gBrowser.selectedBrowser;
switch (aEvent.type) { switch (aEvent.type) {
case "TabClose": case "TabClose":
let browser = gBrowser.getBrowserForTab(aEvent.target); let browserForTab = gBrowser.getBrowserForTab(aEvent.target);
this._removeTrackedSnapshot(-1, browser); this._removeTrackedSnapshot(-1, browserForTab);
break;
case "DOMModalDialogClosed":
this.stopAnimation();
break; break;
case "pageshow": case "pageshow":
case "popstate": if (aEvent.target == browser.contentDocument) {
if (this.isAnimationRunning()) { this.stopAnimation();
if (aEvent.target != gBrowser.selectedBrowser.contentDocument) }
break; break;
case "popstate":
if (aEvent.target == browser.contentDocument.defaultView) {
this.stopAnimation(); this.stopAnimation();
} }
this._historyIndex = gBrowser.webNavigation.sessionHistory.index;
break; break;
case "pagehide": case "pagehide":
if (aEvent.target == gBrowser.selectedBrowser.contentDocument) { if (aEvent.target == browser.contentDocument) {
// Take a snapshot of a page whenever it's about to be navigated away // Take and compress a snapshot of a page whenever it's about to be
// from. // navigated away from. We already have a snapshot of the page if an
this._takeSnapshot(); // animation is running, so we're left with compressing it.
if (!this.isAnimationRunning()) {
this._takeSnapshot();
}
this._compressSnapshotAtCurrentIndex();
} }
break; break;
} }
@ -776,9 +801,10 @@ var gHistorySwipeAnimation = {
* |this|. * |this|.
*/ */
_navigateToHistoryIndex: function() { _navigateToHistoryIndex: function() {
if (this._doesIndexExistInHistory(this._historyIndex)) { if (this._doesIndexExistInHistory(this._historyIndex))
gBrowser.webNavigation.gotoIndex(this._historyIndex); gBrowser.webNavigation.gotoIndex(this._historyIndex);
} else
this.stopAnimation();
}, },
/** /**
@ -866,27 +892,48 @@ var gHistorySwipeAnimation = {
*/ */
_positionBox: function(aBox, aPosition) { _positionBox: function(aBox, aPosition) {
aBox.style.transform = "translateX(" + this._boxWidth * aPosition + "px)"; aBox.style.transform = "translateX(" + this._boxWidth * aPosition + "px)";
let transform = "";
aBox.style.transform = transform;
},
/**
* Verifies that we're ready to take snapshots based on the global pref and
* the current index in history.
*
* @return true if we're ready to take snapshots, false otherwise.
*/
_readyToTakeSnapshots: function() {
if ((this._maxSnapshots < 1) ||
(gBrowser.webNavigation.sessionHistory.index < 0)) {
return false;
}
return true;
}, },
/** /**
* Takes a snapshot of the page the browser is currently on. * Takes a snapshot of the page the browser is currently on.
*/ */
_takeSnapshot: function() { _takeSnapshot: function() {
if ((this._maxSnapshots < 1) || if (!this._readyToTakeSnapshots()) {
(gBrowser.webNavigation.sessionHistory.index < 0))
return; return;
}
let canvas = null;
let browser = gBrowser.selectedBrowser; let browser = gBrowser.selectedBrowser;
let r = browser.getBoundingClientRect(); let r = browser.getBoundingClientRect();
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", canvas = document.createElementNS("http://www.w3.org/1999/xhtml",
"canvas"); "canvas");
canvas.mozOpaque = true; canvas.mozOpaque = true;
canvas.width = r.width; let scale = window.devicePixelRatio;
canvas.height = r.height; canvas.width = r.width * scale;
canvas.height = r.height * scale;
let ctx = canvas.getContext("2d"); let ctx = canvas.getContext("2d");
let zoom = browser.markupDocumentViewer.fullZoom; let zoom = browser.markupDocumentViewer.fullZoom * scale;
ctx.scale(zoom, zoom); ctx.scale(zoom, zoom);
ctx.drawWindow(browser.contentWindow, 0, 0, r.width, r.height, "white", ctx.drawWindow(browser.contentWindow,
0, 0, canvas.width / zoom, canvas.height / zoom, "white",
ctx.DRAWWINDOW_DO_NOT_FLUSH | ctx.DRAWWINDOW_DRAW_VIEW | ctx.DRAWWINDOW_DO_NOT_FLUSH | ctx.DRAWWINDOW_DRAW_VIEW |
ctx.DRAWWINDOW_ASYNC_DECODE_IMAGES | ctx.DRAWWINDOW_ASYNC_DECODE_IMAGES |
ctx.DRAWWINDOW_USE_WIDGET_LAYERS); ctx.DRAWWINDOW_USE_WIDGET_LAYERS);
@ -925,11 +972,34 @@ var gHistorySwipeAnimation = {
// Temporarily store the canvas as the compressed snapshot. // Temporarily store the canvas as the compressed snapshot.
// This avoids a blank page if the user swipes quickly // This avoids a blank page if the user swipes quickly
// between pages before the compression could complete. // between pages before the compression could complete.
snapshots[currIndex] = aCanvas; snapshots[currIndex] = {
image: aCanvas,
scale: window.devicePixelRatio
};
},
/**
* Compresses the HTMLCanvasElement that's stored at the current history
* index in the snapshot array and stores the compressed image in its place.
*/
_compressSnapshotAtCurrentIndex:
function() {
if (!this._readyToTakeSnapshots()) {
// We didn't take a snapshot earlier because we weren't ready to, so
// there's nothing to compress.
return;
}
let browser = gBrowser.selectedBrowser;
let snapshots = browser.snapshots;
let currIndex = browser.webNavigation.sessionHistory.index;
// Kick off snapshot compression. // Kick off snapshot compression.
aCanvas.toBlob(function(aBlob) { let canvas = snapshots[currIndex].image;
snapshots[currIndex] = aBlob; canvas.toBlob(function(aBlob) {
if (snapshots[currIndex]) {
snapshots[currIndex].image = aBlob;
}
}, "image/png" }, "image/png"
); );
}, },
@ -980,6 +1050,7 @@ var gHistorySwipeAnimation = {
while (arr.length > this._maxSnapshots) { while (arr.length > this._maxSnapshots) {
let lastElem = arr[arr.length - 1]; let lastElem = arr[arr.length - 1];
delete lastElem.browser.snapshots[lastElem.index].image;
delete lastElem.browser.snapshots[lastElem.index]; delete lastElem.browser.snapshots[lastElem.index];
arr.splice(-1, 1); arr.splice(-1, 1);
} }
@ -1004,12 +1075,42 @@ var gHistorySwipeAnimation = {
return aBlob; return aBlob;
let img = new Image(); let img = new Image();
let url = URL.createObjectURL(aBlob); let url = "";
img.onload = function() { try {
URL.revokeObjectURL(url); url = URL.createObjectURL(aBlob);
}; img.onload = function() {
img.src = url; URL.revokeObjectURL(url);
return img; };
}
finally {
img.src = url;
return img;
}
},
/**
* Scales the background of a given box element (which uses a given snapshot
* as background) based on a given scale factor.
* @param aSnapshot
* The snapshot that is used as background of aBox.
* @param aScale
* The scale factor to use.
* @param aBox
* The box element that uses aSnapshot as background.
*/
_scaleSnapshot: function(aSnapshot, aScale, aBox) {
if (aSnapshot && aScale != 1 && aBox) {
if (aSnapshot instanceof HTMLCanvasElement) {
aBox.style.backgroundSize =
aSnapshot.width / aScale + "px " + aSnapshot.height / aScale + "px";
} else {
// snapshot is instanceof HTMLImageElement
aSnapshot.addEventListener("load", function() {
aBox.style.backgroundSize =
aSnapshot.width / aScale + "px " + aSnapshot.height / aScale + "px";
});
}
}
}, },
/** /**
@ -1024,12 +1125,17 @@ var gHistorySwipeAnimation = {
_installCurrentPageSnapshot: _installCurrentPageSnapshot:
function(aCanvas) { function(aCanvas) {
let currSnapshot = aCanvas; let currSnapshot = aCanvas;
let scale = window.devicePixelRatio;
if (!currSnapshot) { if (!currSnapshot) {
let snapshots = gBrowser.selectedBrowser.snapshots || {}; let snapshots = gBrowser.selectedBrowser.snapshots || {};
let currIndex = this._historyIndex; let currIndex = this._historyIndex;
if (currIndex in snapshots) if (currIndex in snapshots) {
currSnapshot = this._convertToImg(snapshots[currIndex]); currSnapshot = this._convertToImg(snapshots[currIndex].image);
scale = snapshots[currIndex].scale;
}
} }
this._scaleSnapshot(currSnapshot, scale, this._curBox ? this._curBox :
null);
document.mozSetImageElement("historySwipeAnimationCurrentPageSnapshot", document.mozSetImageElement("historySwipeAnimationCurrentPageSnapshot",
currSnapshot); currSnapshot);
}, },
@ -1044,15 +1150,21 @@ var gHistorySwipeAnimation = {
let currIndex = this._historyIndex; let currIndex = this._historyIndex;
let prevIndex = currIndex - 1; let prevIndex = currIndex - 1;
let prevSnapshot = null; let prevSnapshot = null;
if (prevIndex in snapshots) if (prevIndex in snapshots) {
prevSnapshot = this._convertToImg(snapshots[prevIndex]); prevSnapshot = this._convertToImg(snapshots[prevIndex].image);
this._scaleSnapshot(prevSnapshot, snapshots[prevIndex].scale,
this._prevBox);
}
document.mozSetImageElement("historySwipeAnimationPreviousPageSnapshot", document.mozSetImageElement("historySwipeAnimationPreviousPageSnapshot",
prevSnapshot); prevSnapshot);
let nextIndex = currIndex + 1; let nextIndex = currIndex + 1;
let nextSnapshot = null; let nextSnapshot = null;
if (nextIndex in snapshots) if (nextIndex in snapshots) {
nextSnapshot = this._convertToImg(snapshots[nextIndex]); nextSnapshot = this._convertToImg(snapshots[nextIndex].image);
this._scaleSnapshot(nextSnapshot, snapshots[nextIndex].scale,
this._nextBox);
}
document.mozSetImageElement("historySwipeAnimationNextPageSnapshot", document.mozSetImageElement("historySwipeAnimationNextPageSnapshot",
nextSnapshot); nextSnapshot);
}, },