mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 860493: Add arrow indicators for history swipes on macOS. r=felipe,bram
This commit is contained in:
parent
196c70b995
commit
8e75c6c6bc
@ -236,7 +236,7 @@ var gGestureSupport = {
|
||||
* othwerwise.
|
||||
*/
|
||||
_setupSwipeGesture: function GS__setupSwipeGesture() {
|
||||
gHistorySwipeAnimation.startAnimation(false);
|
||||
gHistorySwipeAnimation.startAnimation();
|
||||
|
||||
this._doUpdate = function GS__doUpdate(aEvent) {
|
||||
gHistorySwipeAnimation.updateAnimation(aEvent.delta);
|
||||
@ -405,12 +405,8 @@ var gGestureSupport = {
|
||||
*/
|
||||
_coordinateSwipeEventWithAnimation:
|
||||
function GS__coordinateSwipeEventWithAnimation(aEvent, aDir) {
|
||||
if ((gHistorySwipeAnimation.isAnimationRunning()) &&
|
||||
(aDir == "RIGHT" || aDir == "LEFT")) {
|
||||
gHistorySwipeAnimation.processSwipeEvent(aEvent, aDir);
|
||||
} else {
|
||||
this.processSwipeEvent(aEvent, aDir);
|
||||
}
|
||||
gHistorySwipeAnimation.stopAnimation();
|
||||
this.processSwipeEvent(aEvent, aDir);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -584,97 +580,60 @@ var gHistorySwipeAnimation = {
|
||||
* by the platform/configuration.
|
||||
*/
|
||||
init: function HSA_init() {
|
||||
if (!this._isSupported())
|
||||
if (!this._isSupported()) {
|
||||
return;
|
||||
|
||||
this.active = false;
|
||||
this.isLTR = document.documentElement.matches(":-moz-locale-dir(ltr)");
|
||||
this._trackedSnapshots = [];
|
||||
this._startingIndex = -1;
|
||||
this._historyIndex = -1;
|
||||
this._boxWidth = -1;
|
||||
this._boxHeight = -1;
|
||||
this._maxSnapshots = this._getMaxSnapshots();
|
||||
this._lastSwipeDir = "";
|
||||
this._direction = "horizontal";
|
||||
|
||||
// We only want to activate history swipe animations if we store snapshots.
|
||||
// If we don't store any, we handle horizontal swipes without animations.
|
||||
if (this._maxSnapshots > 0) {
|
||||
this.active = true;
|
||||
gBrowser.addEventListener("pagehide", this);
|
||||
gBrowser.addEventListener("pageshow", this);
|
||||
gBrowser.addEventListener("popstate", this);
|
||||
gBrowser.addEventListener("DOMModalDialogClosed", this);
|
||||
gBrowser.tabContainer.addEventListener("TabClose", this);
|
||||
}
|
||||
|
||||
this.isLTR = document.documentElement.matches(":-moz-locale-dir(ltr)");
|
||||
this._isStoppingAnimation = false;
|
||||
this.active = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Uninitializes the support for history swipe animations.
|
||||
*/
|
||||
uninit: function HSA_uninit() {
|
||||
gBrowser.removeEventListener("pagehide", this);
|
||||
gBrowser.removeEventListener("pageshow", this);
|
||||
gBrowser.removeEventListener("popstate", this);
|
||||
gBrowser.removeEventListener("DOMModalDialogClosed", this);
|
||||
gBrowser.tabContainer.removeEventListener("TabClose", this);
|
||||
|
||||
this.active = false;
|
||||
this.isLTR = false;
|
||||
this._removeBoxes();
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts the swipe animation and handles fast swiping (i.e. a swipe animation
|
||||
* is already in progress when a new one is initiated).
|
||||
* Starts the swipe animation.
|
||||
*
|
||||
* @param aIsVerticalSwipe
|
||||
* Whether we're dealing with a vertical swipe or not.
|
||||
*/
|
||||
startAnimation: function HSA_startAnimation(aIsVerticalSwipe) {
|
||||
this._direction = aIsVerticalSwipe ? "vertical" : "horizontal";
|
||||
|
||||
startAnimation: function HSA_startAnimation() {
|
||||
if (this.isAnimationRunning()) {
|
||||
// If this is a horizontal scroll, or if this is a vertical scroll that
|
||||
// was started while a horizontal scroll was still running, handle it as
|
||||
// as a fast swipe. In the case of the latter scenario, this allows us to
|
||||
// start the vertical animation without first loading the final page, or
|
||||
// taking another snapshot. If vertical scrolls are initiated repeatedly
|
||||
// without prior horizontal scroll we skip this and restart the animation
|
||||
// from 0.
|
||||
if (this._direction == "horizontal" || this._lastSwipeDir != "") {
|
||||
gBrowser.stop();
|
||||
this._lastSwipeDir = "RELOAD"; // just ensure that != ""
|
||||
this._canGoBack = this.canGoBack();
|
||||
this._canGoForward = this.canGoForward();
|
||||
this._handleFastSwiping();
|
||||
}
|
||||
this.updateAnimation(0);
|
||||
} else {
|
||||
// Get the session history from SessionStore.
|
||||
let updateSessionHistory = sessionHistory => {
|
||||
this._startingIndex = sessionHistory.index;
|
||||
this._historyIndex = this._startingIndex;
|
||||
this._canGoBack = this.canGoBack();
|
||||
this._canGoForward = this.canGoForward();
|
||||
if (this.active) {
|
||||
this._addBoxes();
|
||||
this._takeSnapshot();
|
||||
this._installPrevAndNextSnapshots();
|
||||
this._lastSwipeDir = "";
|
||||
}
|
||||
this.updateAnimation(0);
|
||||
};
|
||||
SessionStore.getSessionHistory(gBrowser.selectedTab, updateSessionHistory);
|
||||
return;
|
||||
}
|
||||
|
||||
this._isStoppingAnimation = false;
|
||||
this._canGoBack = this.canGoBack();
|
||||
this._canGoForward = this.canGoForward();
|
||||
if (this.active) {
|
||||
this._addBoxes();
|
||||
}
|
||||
this.updateAnimation(0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops the swipe animation.
|
||||
*/
|
||||
stopAnimation: function HSA_stopAnimation() {
|
||||
gHistorySwipeAnimation._removeBoxes();
|
||||
this._historyIndex = this._getCurrentHistoryIndex();
|
||||
if (!this.isAnimationRunning()) {
|
||||
return;
|
||||
}
|
||||
this._isStoppingAnimation = true;
|
||||
let box = this._prevBox.style.opacity > 0 ? this._prevBox : this._nextBox;
|
||||
if (box.style.opacity > 0) {
|
||||
box.style.transition = "opacity 0.2s cubic-bezier(.07,.95,0,1)";
|
||||
box.addEventListener("transitionend", this._completeFadeOut);
|
||||
box.style.opacity = 0;
|
||||
} else {
|
||||
this._removeBoxes();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -685,93 +644,28 @@ var gHistorySwipeAnimation = {
|
||||
* swipe gesture.
|
||||
*/
|
||||
updateAnimation: function HSA_updateAnimation(aVal) {
|
||||
if (!this.isAnimationRunning()) {
|
||||
if (!this.isAnimationRunning() || this._isStoppingAnimation) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We use the following value to decrease the bounce effect when scrolling
|
||||
// to the top or bottom of the page, or when swiping back/forward past the
|
||||
// browsing history. This value was determined experimentally.
|
||||
let dampValue = 4;
|
||||
if (this._direction == "vertical") {
|
||||
this._prevBox.collapsed = true;
|
||||
this._nextBox.collapsed = true;
|
||||
this._positionBox(this._curBox, -1 * aVal / dampValue);
|
||||
} else if ((aVal >= 0 && this.isLTR) ||
|
||||
(aVal <= 0 && !this.isLTR)) {
|
||||
let tempDampValue = 1;
|
||||
// We use the following value to set the opacity of the swipe arrows. It was
|
||||
// determined experimentally that absolute values of 0.25 (or greater)
|
||||
// trigger history navigation, hence the multiplier 4 to set the arrows to
|
||||
// full opacity at 0.25 or greater.
|
||||
let opacity = Math.abs(aVal) * 4;
|
||||
if ((aVal >= 0 && this.isLTR) ||
|
||||
(aVal <= 0 && !this.isLTR)) {
|
||||
// The intention is to go back.
|
||||
if (this._canGoBack) {
|
||||
this._prevBox.collapsed = false;
|
||||
} else {
|
||||
tempDampValue = dampValue;
|
||||
this._prevBox.collapsed = true;
|
||||
this._nextBox.collapsed = true;
|
||||
this._prevBox.style.opacity = opacity > 1 ? 1 : opacity;
|
||||
}
|
||||
|
||||
// The current page is pushed to the right (LTR) or left (RTL),
|
||||
// the intention is to go back.
|
||||
// If there is a page to go back to, it should show in the background.
|
||||
this._positionBox(this._curBox, aVal / tempDampValue);
|
||||
|
||||
// The forward page should be pushed offscreen all the way to the right.
|
||||
this._positionBox(this._nextBox, 1);
|
||||
} else if (this._canGoForward) {
|
||||
// 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).
|
||||
// Otherwise, the current page should slide to the left (LTR) or
|
||||
// right (RTL) and the backdrop should appear in the background.
|
||||
// For the backdrop to be visible in that case, the previous page needs
|
||||
// to be hidden (if it exists).
|
||||
// The intention is to go forward.
|
||||
this._nextBox.collapsed = false;
|
||||
let offset = this.isLTR ? 1 : -1;
|
||||
this._positionBox(this._curBox, 0);
|
||||
this._positionBox(this._nextBox, offset + aVal);
|
||||
} else {
|
||||
this._prevBox.collapsed = true;
|
||||
this._positionBox(this._curBox, aVal / dampValue);
|
||||
}
|
||||
},
|
||||
|
||||
_getCurrentHistoryIndex() {
|
||||
return SessionStore.getSessionHistory(gBrowser.selectedTab).index;
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for events relevant to the history swipe animation.
|
||||
*
|
||||
* @param aEvent
|
||||
* An event to process.
|
||||
*/
|
||||
handleEvent: function HSA_handleEvent(aEvent) {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
switch (aEvent.type) {
|
||||
case "TabClose":
|
||||
let browserForTab = gBrowser.getBrowserForTab(aEvent.target);
|
||||
this._removeTrackedSnapshot(-1, browserForTab);
|
||||
break;
|
||||
case "DOMModalDialogClosed":
|
||||
this.stopAnimation();
|
||||
break;
|
||||
case "pageshow":
|
||||
if (aEvent.target == browser.contentDocument) {
|
||||
this.stopAnimation();
|
||||
}
|
||||
break;
|
||||
case "popstate":
|
||||
if (aEvent.target == browser.contentDocument.defaultView) {
|
||||
this.stopAnimation();
|
||||
}
|
||||
break;
|
||||
case "pagehide":
|
||||
if (aEvent.target == browser.contentDocument) {
|
||||
// Take and compress a snapshot of a page whenever it's about to be
|
||||
// navigated away from. We already have a snapshot of the page if an
|
||||
// animation is running, so we're left with compressing it.
|
||||
if (!this.isAnimationRunning()) {
|
||||
this._takeSnapshot();
|
||||
}
|
||||
this._compressSnapshotAtCurrentIndex();
|
||||
}
|
||||
break;
|
||||
this._nextBox.style.opacity = opacity > 1 ? 1 : opacity;
|
||||
}
|
||||
},
|
||||
|
||||
@ -784,32 +678,12 @@ var gHistorySwipeAnimation = {
|
||||
return !!this._container;
|
||||
},
|
||||
|
||||
/**
|
||||
* Process a swipe event based on the given direction.
|
||||
*
|
||||
* @param aEvent
|
||||
* The swipe event to handle
|
||||
* @param aDir
|
||||
* The direction for the swipe event
|
||||
*/
|
||||
processSwipeEvent: function HSA_processSwipeEvent(aEvent, aDir) {
|
||||
if (aDir == "RIGHT")
|
||||
this._historyIndex += this.isLTR ? 1 : -1;
|
||||
else if (aDir == "LEFT")
|
||||
this._historyIndex += this.isLTR ? -1 : 1;
|
||||
else
|
||||
return;
|
||||
this._lastSwipeDir = aDir;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if there is a page in the browser history to go back to.
|
||||
*
|
||||
* @return true if there is a previous page in history, false otherwise.
|
||||
*/
|
||||
canGoBack: function HSA_canGoBack() {
|
||||
if (this.isAnimationRunning())
|
||||
return this._doesIndexExistInHistory(this._historyIndex - 1);
|
||||
return gBrowser.webNavigation.canGoBack;
|
||||
},
|
||||
|
||||
@ -819,8 +693,6 @@ var gHistorySwipeAnimation = {
|
||||
* @return true if there is a next page in history, false otherwise.
|
||||
*/
|
||||
canGoForward: function HSA_canGoForward() {
|
||||
if (this.isAnimationRunning())
|
||||
return this._doesIndexExistInHistory(this._historyIndex + 1);
|
||||
return gBrowser.webNavigation.canGoForward;
|
||||
},
|
||||
|
||||
@ -830,40 +702,7 @@ var gHistorySwipeAnimation = {
|
||||
* any. This will also result in the animation overlay to be torn down.
|
||||
*/
|
||||
swipeEndEventReceived: function HSA_swipeEndEventReceived() {
|
||||
// Update the session history before continuing.
|
||||
let updateSessionHistory = sessionHistory => {
|
||||
if (this._lastSwipeDir != "" && this._historyIndex != this._startingIndex)
|
||||
this._navigateToHistoryIndex();
|
||||
else
|
||||
this.stopAnimation();
|
||||
};
|
||||
SessionStore.getSessionHistory(gBrowser.selectedTab, updateSessionHistory);
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether a particular index exists in the browser history or not.
|
||||
*
|
||||
* @param aIndex
|
||||
* The index to check for availability for in the history.
|
||||
* @return true if the index exists in the browser history, false otherwise.
|
||||
*/
|
||||
_doesIndexExistInHistory: function HSA__doesIndexExistInHistory(aIndex) {
|
||||
try {
|
||||
return SessionStore.getSessionHistory(gBrowser.selectedTab).entries[aIndex] != null;
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Navigates to the index in history that is currently being tracked by
|
||||
* |this|.
|
||||
*/
|
||||
_navigateToHistoryIndex: function HSA__navigateToHistoryIndex() {
|
||||
if (this._doesIndexExistInHistory(this._historyIndex))
|
||||
gBrowser.webNavigation.gotoIndex(this._historyIndex);
|
||||
else
|
||||
this.stopAnimation();
|
||||
this.stopAnimation();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -876,18 +715,12 @@ var gHistorySwipeAnimation = {
|
||||
return window.matchMedia("(-moz-swipe-animation-enabled)").matches;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle fast swiping (i.e. a swipe animation is already in
|
||||
* progress when a new one is initiated). This will swap out the snapshots
|
||||
* used in the previous animation with the appropriate new ones.
|
||||
*/
|
||||
_handleFastSwiping: function HSA__handleFastSwiping() {
|
||||
this._installCurrentPageSnapshot(null);
|
||||
this._installPrevAndNextSnapshots();
|
||||
_completeFadeOut: function HSA__completeFadeOut(aEvent) {
|
||||
gHistorySwipeAnimation._removeBoxes();
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds the boxes that contain the snapshots used during the swipe animation.
|
||||
* Adds the boxes that contain the arrows used during the swipe animation.
|
||||
*/
|
||||
_addBoxes: function HSA__addBoxes() {
|
||||
let browserStack =
|
||||
@ -897,35 +730,28 @@ var gHistorySwipeAnimation = {
|
||||
"stack");
|
||||
browserStack.appendChild(this._container);
|
||||
|
||||
this._prevBox = this._createElement("historySwipeAnimationPreviousPage",
|
||||
this._prevBox = this._createElement("historySwipeAnimationPreviousArrow",
|
||||
"box");
|
||||
this._prevBox.collapsed = true;
|
||||
this._prevBox.style.opacity = 0;
|
||||
this._container.appendChild(this._prevBox);
|
||||
|
||||
this._curBox = this._createElement("historySwipeAnimationCurrentPage",
|
||||
"box");
|
||||
this._container.appendChild(this._curBox);
|
||||
|
||||
this._nextBox = this._createElement("historySwipeAnimationNextPage",
|
||||
this._nextBox = this._createElement("historySwipeAnimationNextArrow",
|
||||
"box");
|
||||
this._nextBox.collapsed = true;
|
||||
this._nextBox.style.opacity = 0;
|
||||
this._container.appendChild(this._nextBox);
|
||||
|
||||
// Cache width and height.
|
||||
this._boxWidth = this._curBox.getBoundingClientRect().width;
|
||||
this._boxHeight = this._curBox.getBoundingClientRect().height;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the boxes.
|
||||
*/
|
||||
_removeBoxes: function HSA__removeBoxes() {
|
||||
this._curBox = null;
|
||||
this._prevBox = null;
|
||||
this._nextBox = null;
|
||||
if (this._container)
|
||||
this._container.remove();
|
||||
this._container = null;
|
||||
this._boxWidth = -1;
|
||||
this._boxHeight = -1;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -943,300 +769,4 @@ var gHistorySwipeAnimation = {
|
||||
element.id = aID;
|
||||
return element;
|
||||
},
|
||||
|
||||
/**
|
||||
* Moves a given box to a given X coordinate position.
|
||||
*
|
||||
* @param aBox
|
||||
* The box element to position.
|
||||
* @param aPosition
|
||||
* The position (in X coordinates) to move the box element to.
|
||||
*/
|
||||
_positionBox: function HSA__positionBox(aBox, aPosition) {
|
||||
let transform = "";
|
||||
|
||||
if (this._direction == "vertical")
|
||||
transform = "translateY(" + this._boxHeight * aPosition + "px)";
|
||||
else
|
||||
transform = "translateX(" + this._boxWidth * aPosition + "px)";
|
||||
|
||||
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 HSA__readyToTakeSnapshots() {
|
||||
return (this._maxSnapshots >= 1 && this._getCurrentHistoryIndex() >= 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Takes a snapshot of the page the browser is currently on.
|
||||
*/
|
||||
_takeSnapshot: function HSA__takeSnapshot() {
|
||||
if (!this._readyToTakeSnapshots()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let canvas = null;
|
||||
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let r = browser.getBoundingClientRect();
|
||||
canvas = document.createElementNS("http://www.w3.org/1999/xhtml",
|
||||
"canvas");
|
||||
canvas.mozOpaque = true;
|
||||
let scale = window.devicePixelRatio;
|
||||
canvas.width = r.width * scale;
|
||||
canvas.height = r.height * scale;
|
||||
let ctx = canvas.getContext("2d");
|
||||
let zoom = browser.markupDocumentViewer.fullZoom * scale;
|
||||
ctx.scale(zoom, zoom);
|
||||
ctx.drawWindow(browser.contentWindow,
|
||||
0, 0, canvas.width / zoom, canvas.height / zoom, "white",
|
||||
ctx.DRAWWINDOW_DO_NOT_FLUSH | ctx.DRAWWINDOW_DRAW_VIEW |
|
||||
ctx.DRAWWINDOW_ASYNC_DECODE_IMAGES |
|
||||
ctx.DRAWWINDOW_USE_WIDGET_LAYERS);
|
||||
|
||||
TelemetryStopwatch.start("FX_GESTURE_INSTALL_SNAPSHOT_OF_PAGE");
|
||||
try {
|
||||
this._installCurrentPageSnapshot(canvas);
|
||||
this._assignSnapshotToCurrentBrowser(canvas);
|
||||
} finally {
|
||||
TelemetryStopwatch.finish("FX_GESTURE_INSTALL_SNAPSHOT_OF_PAGE");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the maximum number of snapshots that should be kept in memory.
|
||||
* This limit is a global limit and is valid across all open tabs.
|
||||
*/
|
||||
_getMaxSnapshots: function HSA__getMaxSnapshots() {
|
||||
return Services.prefs.getIntPref("browser.snapshots.limit");
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a snapshot to the list and initiates the compression of said snapshot.
|
||||
* Once the compression is completed, it will replace the uncompressed
|
||||
* snapshot in the list.
|
||||
*
|
||||
* @param aCanvas
|
||||
* The snapshot to add to the list and compress.
|
||||
*/
|
||||
_assignSnapshotToCurrentBrowser:
|
||||
function HSA__assignSnapshotToCurrentBrowser(aCanvas) {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let currIndex = this._getCurrentHistoryIndex();
|
||||
|
||||
this._removeTrackedSnapshot(currIndex, browser);
|
||||
this._addSnapshotRefToArray(currIndex, browser);
|
||||
|
||||
if (!("snapshots" in browser))
|
||||
browser.snapshots = [];
|
||||
let snapshots = browser.snapshots;
|
||||
// Temporarily store the canvas as the compressed snapshot.
|
||||
// This avoids a blank page if the user swipes quickly
|
||||
// between pages before the compression could complete.
|
||||
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 HSA__compressSnapshotAtCurrentIndex() {
|
||||
if (!this._readyToTakeSnapshots()) {
|
||||
// We didn't take a snapshot earlier because we weren't ready to, so
|
||||
// there's nothing to compress.
|
||||
return;
|
||||
}
|
||||
|
||||
TelemetryStopwatch.start("FX_GESTURE_COMPRESS_SNAPSHOT_OF_PAGE");
|
||||
try {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let snapshots = browser.snapshots;
|
||||
let currIndex = this._getCurrentHistoryIndex();
|
||||
|
||||
// Kick off snapshot compression.
|
||||
let canvas = snapshots[currIndex].image;
|
||||
canvas.toBlob(function(aBlob) {
|
||||
if (snapshots[currIndex]) {
|
||||
snapshots[currIndex].image = aBlob;
|
||||
}
|
||||
}, "image/png"
|
||||
);
|
||||
} finally {
|
||||
TelemetryStopwatch.finish("FX_GESTURE_COMPRESS_SNAPSHOT_OF_PAGE");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes a snapshot identified by the browser and index in the array of
|
||||
* snapshots for that browser, if present. If no snapshot could be identified
|
||||
* the method simply returns without taking any action. If aIndex is negative,
|
||||
* all snapshots for a particular browser will be removed.
|
||||
*
|
||||
* @param aIndex
|
||||
* The index in history of the new snapshot, or negative value if all
|
||||
* snapshots for a browser should be removed.
|
||||
* @param aBrowser
|
||||
* The browser the new snapshot was taken in.
|
||||
*/
|
||||
_removeTrackedSnapshot: function HSA__removeTrackedSnapshot(aIndex, aBrowser) {
|
||||
let arr = this._trackedSnapshots;
|
||||
let requiresExactIndexMatch = aIndex >= 0;
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if ((arr[i].browser == aBrowser) &&
|
||||
(aIndex < 0 || aIndex == arr[i].index)) {
|
||||
delete aBrowser.snapshots[arr[i].index];
|
||||
arr.splice(i, 1);
|
||||
if (requiresExactIndexMatch)
|
||||
return; // Found and removed the only element.
|
||||
i--; // Make sure to revisit the index that we just removed an
|
||||
// element at.
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a new snapshot reference for a given index and browser to the array
|
||||
* of references to tracked snapshots.
|
||||
*
|
||||
* @param aIndex
|
||||
* The index in history of the new snapshot.
|
||||
* @param aBrowser
|
||||
* The browser the new snapshot was taken in.
|
||||
*/
|
||||
_addSnapshotRefToArray:
|
||||
function HSA__addSnapshotRefToArray(aIndex, aBrowser) {
|
||||
let id = { index: aIndex,
|
||||
browser: aBrowser };
|
||||
let arr = this._trackedSnapshots;
|
||||
arr.unshift(id);
|
||||
|
||||
while (arr.length > this._maxSnapshots) {
|
||||
let lastElem = arr[arr.length - 1];
|
||||
delete lastElem.browser.snapshots[lastElem.index].image;
|
||||
delete lastElem.browser.snapshots[lastElem.index];
|
||||
arr.splice(-1, 1);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a compressed blob to an Image object. In some situations
|
||||
* (especially during fast swiping) aBlob may still be a canvas, not a
|
||||
* compressed blob. In this case, we simply return the canvas.
|
||||
*
|
||||
* @param aBlob
|
||||
* The compressed blob to convert, or a canvas if a blob compression
|
||||
* couldn't complete before this method was called.
|
||||
* @return A new Image object representing the converted blob.
|
||||
*/
|
||||
_convertToImg: function HSA__convertToImg(aBlob) {
|
||||
if (!aBlob)
|
||||
return null;
|
||||
|
||||
// Return aBlob if it's still a canvas and not a compressed blob yet.
|
||||
if (aBlob instanceof HTMLCanvasElement)
|
||||
return aBlob;
|
||||
|
||||
let img = new Image();
|
||||
let url = "";
|
||||
try {
|
||||
url = URL.createObjectURL(aBlob);
|
||||
img.onload = function() {
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
} 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 HSA__scaleSnapshot(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";
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the snapshot of the current page to the snapshot passed as parameter,
|
||||
* or to the one previously stored for the current index in history if the
|
||||
* parameter is null.
|
||||
*
|
||||
* @param aCanvas
|
||||
* The snapshot to set the current page to. If this parameter is null,
|
||||
* the previously stored snapshot for this index (if any) will be used.
|
||||
*/
|
||||
_installCurrentPageSnapshot:
|
||||
function HSA__installCurrentPageSnapshot(aCanvas) {
|
||||
let currSnapshot = aCanvas;
|
||||
let scale = window.devicePixelRatio;
|
||||
if (!currSnapshot) {
|
||||
let snapshots = gBrowser.selectedBrowser.snapshots || {};
|
||||
let currIndex = this._historyIndex;
|
||||
if (currIndex in snapshots) {
|
||||
currSnapshot = this._convertToImg(snapshots[currIndex].image);
|
||||
scale = snapshots[currIndex].scale;
|
||||
}
|
||||
}
|
||||
this._scaleSnapshot(currSnapshot, scale, this._curBox ? this._curBox :
|
||||
null);
|
||||
document.mozSetImageElement("historySwipeAnimationCurrentPageSnapshot",
|
||||
currSnapshot);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the snapshots of the previous and next pages to the snapshots
|
||||
* previously stored for their respective indeces.
|
||||
*/
|
||||
_installPrevAndNextSnapshots:
|
||||
function HSA__installPrevAndNextSnapshots() {
|
||||
let snapshots = gBrowser.selectedBrowser.snapshots || [];
|
||||
let currIndex = this._historyIndex;
|
||||
let prevIndex = currIndex - 1;
|
||||
let prevSnapshot = null;
|
||||
if (prevIndex in snapshots) {
|
||||
prevSnapshot = this._convertToImg(snapshots[prevIndex].image);
|
||||
this._scaleSnapshot(prevSnapshot, snapshots[prevIndex].scale,
|
||||
this._prevBox);
|
||||
}
|
||||
document.mozSetImageElement("historySwipeAnimationPreviousPageSnapshot",
|
||||
prevSnapshot);
|
||||
|
||||
let nextIndex = currIndex + 1;
|
||||
let nextSnapshot = null;
|
||||
if (nextIndex in snapshots) {
|
||||
nextSnapshot = this._convertToImg(snapshots[nextIndex].image);
|
||||
this._scaleSnapshot(nextSnapshot, snapshots[nextIndex].scale,
|
||||
this._nextBox);
|
||||
}
|
||||
document.mozSetImageElement("historySwipeAnimationNextPageSnapshot",
|
||||
nextSnapshot);
|
||||
},
|
||||
};
|
||||
|
@ -887,24 +887,17 @@ window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#pri
|
||||
|
||||
#historySwipeAnimationContainer {
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#historySwipeAnimationPreviousPage,
|
||||
#historySwipeAnimationCurrentPage,
|
||||
#historySwipeAnimationNextPage {
|
||||
background: none top left no-repeat white;
|
||||
#historySwipeAnimationPreviousArrow {
|
||||
background: url("chrome://browser/content/history-swipe-arrow.svg")
|
||||
center left / 64px 128px no-repeat transparent;
|
||||
}
|
||||
|
||||
#historySwipeAnimationPreviousPage {
|
||||
background-image: -moz-element(#historySwipeAnimationPreviousPageSnapshot);
|
||||
}
|
||||
|
||||
#historySwipeAnimationCurrentPage {
|
||||
background-image: -moz-element(#historySwipeAnimationCurrentPageSnapshot);
|
||||
}
|
||||
|
||||
#historySwipeAnimationNextPage {
|
||||
background-image: -moz-element(#historySwipeAnimationNextPageSnapshot);
|
||||
#historySwipeAnimationNextArrow {
|
||||
background: url("chrome://browser/content/history-swipe-arrow.svg")
|
||||
center left / 64px 128px no-repeat transparent;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* Full Screen UI */
|
||||
|
4
browser/base/content/history-swipe-arrow.svg
Normal file
4
browser/base/content/history-swipe-arrow.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="256" height="512" xmlns="http://www.w3.org/2000/svg">
|
||||
<ellipse ry="256" rx="256" cy="256" cx="0" stroke-width="0" stroke="#000" fill="#38383d"/>
|
||||
<path d="m181.335236,247.749695l-96.549957,0l35.774963,-35.774994a8.33333,8.33333 0 0 0 -11.783325,-11.783325l-49.999969,49.999954a8.33333,8.33333 0 0 0 0,11.782944l49.999969,50a8.33333,8.33333 0 0 0 11.783325,-11.783325l-35.774963,-35.774994l96.549957,0a8.33333,8.33333 0 0 0 0,-16.66626z" fill="rgba(249, 249, 250, .8)"/>
|
||||
</svg>
|
After Width: | Height: | Size: 491 B |
@ -96,6 +96,7 @@ browser.jar:
|
||||
content/browser/defaultthemes/5.preview.jpg (content/defaultthemes/5.preview.jpg)
|
||||
content/browser/defaultthemes/dark.icon.svg (content/defaultthemes/dark.icon.svg)
|
||||
content/browser/defaultthemes/light.icon.svg (content/defaultthemes/light.icon.svg)
|
||||
content/browser/history-swipe-arrow.svg (content/history-swipe-arrow.svg)
|
||||
* content/browser/pageinfo/pageInfo.xul (content/pageinfo/pageInfo.xul)
|
||||
content/browser/pageinfo/pageInfo.js (content/pageinfo/pageInfo.js)
|
||||
content/browser/pageinfo/pageInfo.css (content/pageinfo/pageInfo.css)
|
||||
|
@ -638,18 +638,6 @@ html|input.urlbar-input {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
/* History Swipe Animation */
|
||||
|
||||
#historySwipeAnimationCurrentPage,
|
||||
#historySwipeAnimationNextPage {
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
#historySwipeAnimationContainer {
|
||||
background: url("chrome://browser/skin/subtle-pattern.png") #B3B9C1;
|
||||
}
|
||||
|
||||
|
||||
/* ----- SIDEBAR ELEMENTS ----- */
|
||||
|
||||
%include ../shared/sidebar.inc.css
|
||||
|
@ -9,7 +9,6 @@ browser.jar:
|
||||
* skin/classic/browser/syncedtabs/sidebar.css (syncedtabs/sidebar.css)
|
||||
* skin/classic/browser/browser.css
|
||||
* skin/classic/browser/compacttheme.css
|
||||
skin/classic/browser/subtle-pattern.png
|
||||
skin/classic/browser/panel-expander-closed.png
|
||||
skin/classic/browser/panel-expander-closed@2x.png
|
||||
skin/classic/browser/panel-expander-open.png
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 11 KiB |
Loading…
Reference in New Issue
Block a user