зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to m-i
This commit is contained in:
Коммит
b449e715d1
|
@ -895,6 +895,12 @@
|
|||
#endif
|
||||
</toolbar>
|
||||
|
||||
<hbox id="downloads-animation-container" mousethrough="always">
|
||||
<vbox id="downloads-notification-anchor">
|
||||
<vbox id="downloads-indicator-notification"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
<toolbarpalette id="BrowserToolbarPalette">
|
||||
|
||||
# Update primaryToolbarButtons in browser/themes/shared/browser.inc when adding
|
||||
|
@ -912,16 +918,8 @@
|
|||
ondrop="DownloadsIndicatorView.onDrop(event);"
|
||||
ondragover="DownloadsIndicatorView.onDragOver(event);"
|
||||
ondragenter="DownloadsIndicatorView.onDragOver(event);"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
label="&downloads.label;"
|
||||
tooltiptext="&downloads.tooltip;">
|
||||
<!-- We need a different binding for the notification and progress bar, which means
|
||||
we don't get these for free. Adding them in our binding loses them when dragging
|
||||
to the customize window, so we add them in here as 'real' children -->
|
||||
<image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label"/>
|
||||
<label class="toolbarbutton-text" crop="right" flex="1"
|
||||
xbl:inherits="value=label,accesskey,crop"/>
|
||||
</toolbarbutton>
|
||||
tooltiptext="&downloads.tooltip;"/>
|
||||
|
||||
<toolbarbutton id="history-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
observes="viewHistorySidebar" label="&historyButton.label;"
|
||||
|
|
|
@ -111,6 +111,9 @@
|
|||
extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton">
|
||||
<content>
|
||||
<children />
|
||||
<xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label"/>
|
||||
<xul:label class="toolbarbutton-text" crop="right" flex="1"
|
||||
xbl:inherits="value=label,accesskey,crop"/>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
||||
|
|
|
@ -326,18 +326,39 @@ const DownloadsIndicatorView = {
|
|||
return;
|
||||
}
|
||||
|
||||
function DIV_SEN_callback() {
|
||||
if (this._notificationTimeout) {
|
||||
clearTimeout(this._notificationTimeout);
|
||||
}
|
||||
|
||||
let indicator = this.indicator;
|
||||
indicator.setAttribute("notification", aType);
|
||||
this._notificationTimeout = setTimeout(
|
||||
function () indicator.removeAttribute("notification"), 1000);
|
||||
// If the anchor is not there or its container is hidden, don't show
|
||||
// a notification
|
||||
let anchor = DownloadsButton._placeholder;
|
||||
if (!anchor || !isElementVisible(anchor.parentNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._ensureOperational(DIV_SEN_callback.bind(this));
|
||||
if (this._notificationTimeout) {
|
||||
clearTimeout(this._notificationTimeout);
|
||||
}
|
||||
|
||||
// The notification element is positioned to show in the same location as
|
||||
// the downloads button. It's not in the downloads button itself in order to
|
||||
// be able to anchor the notification elsewhere if required, and to ensure
|
||||
// the notification isn't clipped by overflow properties of the anchor's
|
||||
// container.
|
||||
let notifier = this.notifier;
|
||||
if (notifier.style.transform == '') {
|
||||
let anchorRect = anchor.getBoundingClientRect();
|
||||
let notifierRect = notifier.getBoundingClientRect();
|
||||
let topDiff = anchorRect.top - notifierRect.top;
|
||||
let leftDiff = anchorRect.left - notifierRect.left;
|
||||
let heightDiff = anchorRect.height - notifierRect.height;
|
||||
let widthDiff = anchorRect.width - notifierRect.width;
|
||||
let translateX = (leftDiff + .5 * widthDiff) + "px";
|
||||
let translateY = (topDiff + .5 * heightDiff) + "px";
|
||||
notifier.style.transform = "translate(" + translateX + ", " + translateY + ")";
|
||||
}
|
||||
notifier.setAttribute("notification", aType);
|
||||
this._notificationTimeout = setTimeout(function () {
|
||||
notifier.removeAttribute("notification");
|
||||
notifier.style.transform = '';
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -547,6 +568,12 @@ const DownloadsIndicatorView = {
|
|||
(this.__indicatorProgress = document.getElementById("downloads-indicator-progress"));
|
||||
},
|
||||
|
||||
get notifier()
|
||||
{
|
||||
return this._notifier ||
|
||||
(this._notifier = document.getElementById("downloads-notification-anchor"));
|
||||
},
|
||||
|
||||
_onCustomizedAway: function() {
|
||||
this._indicator = null;
|
||||
this._indicatorAnchor = null;
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
min="0" max="100"/>
|
||||
</vbox>
|
||||
<vbox id="downloads-indicator-icon"/>
|
||||
<vbox id="downloads-indicator-notification"/>
|
||||
</stack>
|
||||
</toolbarbutton>
|
||||
</overlay>
|
||||
|
|
|
@ -524,9 +524,6 @@
|
|||
this._xslideHandler = new CrossSlide.Handler(this, {
|
||||
REARRANGESTART: this.crossSlideBoundary
|
||||
});
|
||||
this.addEventListener("touchstart", this._xslideHandler, false);
|
||||
this.addEventListener("touchmove", this._xslideHandler, false);
|
||||
this.addEventListener("touchend", this._xslideHandler, false);
|
||||
}
|
||||
|
||||
// XXX This event was never actually implemented (bug 223411).
|
||||
|
|
|
@ -28,9 +28,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PdfJs",
|
||||
"resource://pdf.js/PdfJs.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
|
||||
"resource://gre/modules/DownloadUtils.jsm");
|
||||
|
||||
|
|
|
@ -148,7 +148,6 @@ var BrowserUI = {
|
|||
DialogUI.init();
|
||||
FormHelperUI.init();
|
||||
FindHelperUI.init();
|
||||
PdfJs.init();
|
||||
} catch(ex) {
|
||||
Util.dumpLn("Exception in delay load module:", ex.message);
|
||||
}
|
||||
|
|
|
@ -432,9 +432,10 @@ MenuPopup.prototype = {
|
|||
let deferred = Promise.defer();
|
||||
|
||||
window.addEventListener("keypress", this, true);
|
||||
window.addEventListener("click", this, true);
|
||||
window.addEventListener("mousedown", this, true);
|
||||
window.addEventListener("touchstart", this, true);
|
||||
window.addEventListener("scroll", this, true);
|
||||
Elements.stack.addEventListener("PopupChanged", this, false);
|
||||
Elements.browsers.addEventListener("PanBegin", this, false);
|
||||
|
||||
this._panel.hidden = false;
|
||||
let popupFrom = !aPositionOptions.bottomAligned ? "above" : "below";
|
||||
|
@ -461,9 +462,10 @@ MenuPopup.prototype = {
|
|||
let deferred = Promise.defer();
|
||||
|
||||
window.removeEventListener("keypress", this, true);
|
||||
window.removeEventListener("click", this, true);
|
||||
window.removeEventListener("mousedown", this, true);
|
||||
window.removeEventListener("touchstart", this, true);
|
||||
window.removeEventListener("scroll", this, true);
|
||||
Elements.stack.removeEventListener("PopupChanged", this, false);
|
||||
Elements.browsers.removeEventListener("PanBegin", this, false);
|
||||
|
||||
let self = this;
|
||||
this._panel.addEventListener("transitionend", function popuphidden() {
|
||||
|
@ -499,7 +501,9 @@ MenuPopup.prototype = {
|
|||
this.hide();
|
||||
}
|
||||
break;
|
||||
case "click":
|
||||
case "mousedown":
|
||||
case "touchstart":
|
||||
case "scroll":
|
||||
if (!this._popup.contains(aEvent.target)) {
|
||||
aEvent.stopPropagation();
|
||||
this.hide();
|
||||
|
@ -517,9 +521,6 @@ MenuPopup.prototype = {
|
|||
this.hide();
|
||||
}
|
||||
break;
|
||||
case "PanBegin":
|
||||
this.hide();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -98,9 +98,11 @@ gTests.push({
|
|||
"context-copy-link"]);
|
||||
|
||||
promise = waitForEvent(document, "popuphidden");
|
||||
ContextMenuUI.hide();
|
||||
yield promise;
|
||||
win.scrollBy(0, 1);
|
||||
let hidden = yield promise;
|
||||
ok(hidden && !(hidden instanceof Error), "scrolling hides the context menu");
|
||||
win.getSelection().removeAllRanges();
|
||||
win.scrollBy(0, -1);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Context menu in content on a link
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<div style="margin: 0; padding: 5px;">
|
||||
<div style="margin: 0; padding: 5px; margin-bottom: 9999px;">
|
||||
<span id="text4">hello, I'm sorry but I must be going.</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -91,6 +91,7 @@ gTests.push({
|
|||
tearDown: setUpAndTearDown,
|
||||
run: function test() {
|
||||
gInput.selectionStart = gInput.selectionEnd = gInput.value.length;
|
||||
yield waitForEvent(window, "scroll");
|
||||
|
||||
let promise = waitForEvent(document, "popupshown");
|
||||
sendContextMenuClick(190, 17);
|
||||
|
@ -137,6 +138,7 @@ gTests.push({
|
|||
tearDown: setUpAndTearDown,
|
||||
run: function test() {
|
||||
gInput.selectionStart = gInput.selectionEnd = 0;
|
||||
yield waitForEvent(window, "scroll");
|
||||
|
||||
let promise = waitForEvent(document, "popupshown");
|
||||
sendContextMenuClick(230, 17);
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -101,6 +101,11 @@ function CrossSlideHandler(aNode, aThresholds) {
|
|||
for(let key in aThresholds)
|
||||
this.thresholds[key] = aThresholds[key];
|
||||
}
|
||||
aNode.addEventListener("touchstart", this, false);
|
||||
aNode.addEventListener("touchmove", this, false);
|
||||
aNode.addEventListener("touchend", this, false);
|
||||
aNode.addEventListener("touchcancel", this, false);
|
||||
aNode.ownerDocument.defaultView.addEventListener("scroll", this, false);
|
||||
}
|
||||
|
||||
CrossSlideHandler.prototype = {
|
||||
|
@ -135,6 +140,10 @@ CrossSlideHandler.prototype = {
|
|||
case "touchmove":
|
||||
this._onTouchMove(aEvent);
|
||||
break;
|
||||
case "scroll":
|
||||
case "touchcancel":
|
||||
this.cancel(aEvent);
|
||||
break;
|
||||
case "touchend":
|
||||
this._onTouchEnd(aEvent);
|
||||
break;
|
||||
|
|
|
@ -42,6 +42,10 @@ pref("gfx.azpc.fling_repaint_interval", "50"); // prefer 20 fps
|
|||
pref("gfx.axis.fling_friction", "0.002");
|
||||
pref("gfx.axis.fling_stopped_threshold", "0.2");
|
||||
|
||||
// 0 = free, 1 = standard, 2 = sticky
|
||||
pref("apzc.axis_lock_mode", 2);
|
||||
pref("apzc.cross_slide.enabled", true);
|
||||
|
||||
// Enable Microsoft TSF support by default for imes.
|
||||
pref("intl.enable_tsf_support", true);
|
||||
|
||||
|
@ -564,10 +568,10 @@ pref("browser.chrome.toolbar_tips", false);
|
|||
// Completely disable pdf.js as an option to preview pdfs within firefox.
|
||||
// Note: if this is not disabled it does not necessarily mean pdf.js is the pdf
|
||||
// handler just that it is an option.
|
||||
pref("pdfjs.disabled", false);
|
||||
pref("pdfjs.disabled", true);
|
||||
// Used by pdf.js to know the first time firefox is run with it installed so it
|
||||
// can become the default pdf viewer.
|
||||
pref("pdfjs.firstRun", true);
|
||||
pref("pdfjs.firstRun", false);
|
||||
// The values of preferredAction and alwaysAskBeforeHandling before pdf.js
|
||||
// became the default.
|
||||
pref("pdfjs.previousHandler.preferredAction", 0);
|
||||
|
|
|
@ -601,6 +601,14 @@ documenttab[selected] .documenttab-selection {
|
|||
list-style-image: url("chrome://browser/skin/images/identity-icons-https-ev.png");
|
||||
}
|
||||
|
||||
#toolbar[startpage] > #urlbar:not([autocomplete]) > #identity-box > #identity-icon {
|
||||
list-style-image: url("chrome://browser/skin/images/icons-identity-firefox.png");
|
||||
}
|
||||
|
||||
#urlbar[autocomplete] > #identity-box > #identity-icon {
|
||||
list-style-image: url("chrome://browser/skin/images/icon-autocomplete-search.png");
|
||||
}
|
||||
|
||||
/* Main URL textbox */
|
||||
#urlbar-edit {
|
||||
margin: 0 !important;
|
||||
|
@ -679,6 +687,14 @@ documenttab[selected] .documenttab-selection {
|
|||
#stop-button {
|
||||
list-style-image: url(chrome://browser/skin/images/urlbar-stop@1.4x.png);
|
||||
}
|
||||
|
||||
#toolbar[startpage] > #urlbar:not([autocomplete]) > #identity-box > #identity-icon {
|
||||
list-style-image: url("chrome://browser/skin/images/icons-identity-firefox@1.4x.png");
|
||||
}
|
||||
|
||||
#urlbar[autocomplete] > #identity-box > #identity-icon {
|
||||
list-style-image: url("chrome://browser/skin/images/icon-autocomplete-search@1.4x.png");
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-resolution: @min_res_180pc@) {
|
||||
|
@ -705,6 +721,14 @@ documenttab[selected] .documenttab-selection {
|
|||
#stop-button {
|
||||
list-style-image: url(chrome://browser/skin/images/urlbar-stop@1.8x.png);
|
||||
}
|
||||
|
||||
#toolbar[startpage] > #urlbar:not([autocomplete]) > #identity-box > #identity-icon {
|
||||
list-style-image: url("chrome://browser/skin/images/icons-identity-firefox@1.8x.png");
|
||||
}
|
||||
|
||||
#urlbar[autocomplete] > #identity-box > #identity-icon {
|
||||
list-style-image: url("chrome://browser/skin/images/icon-autocomplete-search@1.8x.png");
|
||||
}
|
||||
}
|
||||
|
||||
/* navbar edit button: one button out of three - when editing: go, when !editing,
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 338 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 459 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 574 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 348 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 503 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 714 B |
|
@ -56,6 +56,12 @@ chrome.jar:
|
|||
skin/images/identity-icons-https-ev.png (images/identity-icons-https-ev.png)
|
||||
skin/images/identity-icons-https-mixed.png (images/identity-icons-https-mixed.png)
|
||||
skin/images/identity-icons-https.png (images/identity-icons-https.png)
|
||||
skin/images/icon-autocomplete-search.png (images/icon-autocomplete-search.png)
|
||||
skin/images/icon-autocomplete-search@1.4x.png (images/icon-autocomplete-search@1.4x.png)
|
||||
skin/images/icon-autocomplete-search@1.8x.png (images/icon-autocomplete-search@1.8x.png)
|
||||
skin/images/icons-identity-firefox.png (images/icons-identity-firefox.png)
|
||||
skin/images/icons-identity-firefox@1.4x.png (images/icons-identity-firefox@1.4x.png)
|
||||
skin/images/icons-identity-firefox@1.8x.png (images/icons-identity-firefox@1.8x.png)
|
||||
skin/images/infobar-close.png (images/infobar-close.png)
|
||||
skin/images/infobar-geolocation.png (images/infobar-geolocation.png)
|
||||
skin/images/infobar-key.png (images/infobar-key.png)
|
||||
|
|
|
@ -4,11 +4,17 @@
|
|||
|
||||
/*** Status and progress indicator ***/
|
||||
|
||||
#downloads-indicator-anchor {
|
||||
/* Makes the outermost stack element positioned, so that its contents are
|
||||
rendered over the main browser window in the Z order. This is required by
|
||||
the animated event notification. */
|
||||
#downloads-animation-container {
|
||||
min-height: 1px;
|
||||
min-width: 1px;
|
||||
height: 1px;
|
||||
margin-bottom: -1px;
|
||||
/* Makes the outermost animation container element positioned, so that its
|
||||
contents are rendered over the main browser window in the Z order.
|
||||
This is required by the animated event notification. */
|
||||
position: relative;
|
||||
/* The selected tab may overlap #downloads-indicator-notification */
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
toolbar[iconsize="small"] > #downloads-button > #downloads-indicator-anchor {
|
||||
|
@ -61,6 +67,8 @@ toolbar[iconsize="large"] > #downloads-button[attention] > #downloads-indicator-
|
|||
background-size: 16px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartRight {
|
||||
|
@ -75,13 +83,13 @@ toolbar[iconsize="large"] > #downloads-button[attention] > #downloads-indicator-
|
|||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
#downloads-button[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="start"] > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
|
||||
animation-name: downloadsIndicatorNotificationStartRight;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
#downloads-button[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-notification {
|
||||
animation-name: downloadsIndicatorNotificationStartLeft;
|
||||
}
|
||||
|
||||
|
@ -91,7 +99,7 @@ toolbar[iconsize="large"] > #downloads-button[attention] > #downloads-indicator-
|
|||
to { opacity: 0; transform: scale(8); }
|
||||
}
|
||||
|
||||
#downloads-button[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="finish"] > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
|
||||
animation-name: downloadsIndicatorNotificationFinish;
|
||||
animation-duration: 1s;
|
||||
|
|
|
@ -7,12 +7,19 @@
|
|||
#downloads-indicator-anchor {
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
/* Makes the outermost stack element positioned, so that its contents are
|
||||
rendered over the main browser window in the Z order. This is required by
|
||||
the animated event notification. */
|
||||
}
|
||||
|
||||
#downloads-animation-container {
|
||||
min-height: 1px;
|
||||
min-width: 1px;
|
||||
height: 1px;
|
||||
margin-bottom: -1px;
|
||||
/* Makes the outermost animation container element positioned, so that its
|
||||
contents are rendered over the main browser window in the Z order.
|
||||
This is required by the animated event notification. */
|
||||
position: relative;
|
||||
/* The selected tab may overlap #downloads-indicator-notification */
|
||||
z-index: 1;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
/*** Main indicator icon ***/
|
||||
|
@ -71,6 +78,8 @@
|
|||
background-size: 16px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartRight {
|
||||
|
@ -85,19 +94,19 @@
|
|||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
#downloads-button[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="start"] > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
|
||||
animation-name: downloadsIndicatorNotificationStartRight;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#downloads-button[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="start"] > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
#downloads-button[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-notification {
|
||||
animation-name: downloadsIndicatorNotificationStartLeft;
|
||||
}
|
||||
|
||||
|
@ -107,14 +116,14 @@
|
|||
to { opacity: 0; transform: scale(8); }
|
||||
}
|
||||
|
||||
#downloads-button[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="finish"] > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
|
||||
animation-name: downloadsIndicatorNotificationFinish;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#downloads-button[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="finish"] > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish@2x.png");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,17 @@
|
|||
|
||||
/*** Status and progress indicator ***/
|
||||
|
||||
#downloads-indicator-anchor {
|
||||
/* Makes the outermost stack element positioned, so that its contents are
|
||||
rendered over the main browser window in the Z order. This is required by
|
||||
the animated event notification. */
|
||||
#downloads-animation-container {
|
||||
min-height: 1px;
|
||||
min-width: 1px;
|
||||
height: 1px;
|
||||
margin-bottom: -1px;
|
||||
/* Makes the outermost animation container element positioned, so that its
|
||||
contents are rendered over the main browser window in the Z order.
|
||||
This is required by the animated event notification. */
|
||||
position: relative;
|
||||
/* The selected tab may overlap #downloads-indicator-notification */
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
/*** Main indicator icon ***/
|
||||
|
@ -49,6 +55,8 @@
|
|||
background-size: 16px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
@keyframes downloadsIndicatorNotificationStartRight {
|
||||
|
@ -63,13 +71,13 @@
|
|||
to { opacity: 0; transform: translate(0) scale(1); }
|
||||
}
|
||||
|
||||
#downloads-button[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="start"] > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
|
||||
animation-name: downloadsIndicatorNotificationStartRight;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
#downloads-button[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-notification {
|
||||
animation-name: downloadsIndicatorNotificationStartLeft;
|
||||
}
|
||||
|
||||
|
@ -79,7 +87,7 @@
|
|||
to { opacity: 0; transform: scale(8); }
|
||||
}
|
||||
|
||||
#downloads-button[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
|
||||
#downloads-notification-anchor[notification="finish"] > #downloads-indicator-notification {
|
||||
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
|
||||
animation-name: downloadsIndicatorNotificationFinish;
|
||||
animation-duration: 1s;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* 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/. */
|
||||
|
@ -21,6 +21,7 @@
|
|||
#include "gfxTypes.h" // for gfxFloat
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
|
||||
#include "mozilla/Constants.h" // for M_PI
|
||||
#include "mozilla/EventForwards.h" // for nsEventStatus_*
|
||||
#include "mozilla/Preferences.h" // for Preferences
|
||||
#include "mozilla/ReentrantMonitor.h" // for ReentrantMonitorAutoEnter, etc
|
||||
|
@ -64,7 +65,27 @@ namespace layers {
|
|||
*/
|
||||
static float gTouchStartTolerance = 1.0f/16.0f;
|
||||
|
||||
static const float EPSILON = 0.0001;
|
||||
static const float EPSILON = 0.0001f;
|
||||
|
||||
/**
|
||||
* Angle from axis within which we stay axis-locked
|
||||
*/
|
||||
static const double AXIS_LOCK_ANGLE = M_PI / 6.0; // 30 degrees
|
||||
|
||||
/**
|
||||
* The distance in inches the user must pan before axis lock can be broken
|
||||
*/
|
||||
static const float AXIS_BREAKOUT_THRESHOLD = 1.0f/32.0f;
|
||||
|
||||
/**
|
||||
* The angle at which axis lock can be broken
|
||||
*/
|
||||
static const double AXIS_BREAKOUT_ANGLE = M_PI / 8.0; // 22.5 degrees
|
||||
|
||||
/**
|
||||
* The preferred axis locking style. See AxisLockMode for possible values.
|
||||
*/
|
||||
static int32_t gAxisLockMode = 0;
|
||||
|
||||
/**
|
||||
* Maximum amount of time while panning before sending a viewport change. This
|
||||
|
@ -153,6 +174,28 @@ static int gAsyncScrollTimeout = 300;
|
|||
*/
|
||||
static bool gAsyncZoomDisabled = false;
|
||||
|
||||
/**
|
||||
* Pref that enables integration with the Metro "cross-slide" gesture.
|
||||
*/
|
||||
static bool gCrossSlideEnabled = false;
|
||||
|
||||
/**
|
||||
* Is aAngle within the given threshold of the horizontal axis?
|
||||
* @param aAngle an angle in radians in the range [0, pi]
|
||||
* @param aThreshold an angle in radians in the range [0, pi/2]
|
||||
*/
|
||||
static bool IsCloseToHorizontal(float aAngle, float aThreshold)
|
||||
{
|
||||
return (aAngle < aThreshold || aAngle > (M_PI - aThreshold));
|
||||
}
|
||||
|
||||
// As above, but for the vertical axis.
|
||||
static bool IsCloseToVertical(float aAngle, float aThreshold)
|
||||
{
|
||||
return (fabs(aAngle - (M_PI / 2)) < aThreshold);
|
||||
}
|
||||
|
||||
|
||||
static TimeStamp sFrameTime;
|
||||
|
||||
static TimeStamp
|
||||
|
@ -191,6 +234,8 @@ AsyncPanZoomController::InitializeGlobalState()
|
|||
Preferences::AddIntVarCache(&gAsyncScrollThrottleTime, "apzc.asyncscroll.throttle", gAsyncScrollThrottleTime);
|
||||
Preferences::AddIntVarCache(&gAsyncScrollTimeout, "apzc.asyncscroll.timeout", gAsyncScrollTimeout);
|
||||
Preferences::AddBoolVarCache(&gAsyncZoomDisabled, "apzc.asynczoom.disabled", gAsyncZoomDisabled);
|
||||
Preferences::AddBoolVarCache(&gCrossSlideEnabled, "apzc.cross_slide.enabled", gCrossSlideEnabled);
|
||||
Preferences::AddIntVarCache(&gAxisLockMode, "apzc.axis_lock_mode", gAxisLockMode);
|
||||
|
||||
gComputedTimingFunction = new ComputedTimingFunction();
|
||||
gComputedTimingFunction->Init(
|
||||
|
@ -272,6 +317,11 @@ AsyncPanZoomController::GetTouchStartTolerance()
|
|||
return gTouchStartTolerance;
|
||||
}
|
||||
|
||||
/* static */AsyncPanZoomController::AxisLockMode AsyncPanZoomController::GetAxisLockMode()
|
||||
{
|
||||
return static_cast<AxisLockMode>(gAxisLockMode);
|
||||
}
|
||||
|
||||
static CSSPoint
|
||||
WidgetSpaceToCompensatedViewportSpace(const ScreenPoint& aPoint,
|
||||
const CSSToScreenScale& aCurrentZoom)
|
||||
|
@ -295,7 +345,7 @@ nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent)
|
|||
// responding in a timely fashion, this only introduces a nearly constant few
|
||||
// hundred ms of lag.
|
||||
if (mFrameMetrics.mMayHaveTouchListeners && aEvent.mInputType == MULTITOUCH_INPUT &&
|
||||
(mState == NOTHING || mState == TOUCHING || mState == PANNING)) {
|
||||
(mState == NOTHING || mState == TOUCHING || IsPanningState(mState))) {
|
||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_START) {
|
||||
SetState(WAITING_LISTENERS);
|
||||
|
@ -389,9 +439,7 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent)
|
|||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent) {
|
||||
SingleTouchData& touch = GetFirstSingleTouch(aEvent);
|
||||
|
||||
ScreenIntPoint point = touch.mScreenPoint;
|
||||
ScreenIntPoint point = GetFirstTouchScreenPoint(aEvent);
|
||||
|
||||
switch (mState) {
|
||||
case ANIMATING_ZOOM:
|
||||
|
@ -415,6 +463,10 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent
|
|||
break;
|
||||
case TOUCHING:
|
||||
case PANNING:
|
||||
case PANNING_LOCKED_X:
|
||||
case PANNING_LOCKED_Y:
|
||||
case CROSS_SLIDING_X:
|
||||
case CROSS_SLIDING_Y:
|
||||
case PINCHING:
|
||||
case WAITING_LISTENERS:
|
||||
NS_WARNING("Received impossible touch in OnTouchStart");
|
||||
|
@ -440,6 +492,12 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent)
|
|||
// second tap. Ignore the move if this happens.
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case CROSS_SLIDING_X:
|
||||
case CROSS_SLIDING_Y:
|
||||
// While cross-sliding, we don't want to consume any touchmove events for
|
||||
// panning or zooming, and let the caller handle them instead.
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case TOUCHING: {
|
||||
float panThreshold = gTouchStartTolerance * APZCTreeManager::GetDPI();
|
||||
UpdateWithTouchAtDevicePoint(aEvent);
|
||||
|
@ -448,12 +506,12 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent)
|
|||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
StartPanning(aEvent);
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
return StartPanning(aEvent);
|
||||
}
|
||||
|
||||
case PANNING:
|
||||
case PANNING_LOCKED_X:
|
||||
case PANNING_LOCKED_Y:
|
||||
TrackTouch(aEvent);
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
|
||||
|
@ -493,10 +551,14 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
|||
return nsEventStatus_eIgnore;
|
||||
|
||||
case TOUCHING:
|
||||
case CROSS_SLIDING_X:
|
||||
case CROSS_SLIDING_Y:
|
||||
SetState(NOTHING);
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case PANNING:
|
||||
case PANNING_LOCKED_X:
|
||||
case PANNING_LOCKED_Y:
|
||||
{
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
ScheduleComposite();
|
||||
|
@ -705,19 +767,56 @@ const gfx::Point AsyncPanZoomController::GetAccelerationVector() {
|
|||
return gfx::Point(mX.GetAccelerationFactor(), mY.GetAccelerationFactor());
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) {
|
||||
float dx = mX.PanDistance(),
|
||||
dy = mY.PanDistance();
|
||||
nsEventStatus AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) {
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
ScreenIntPoint point = GetFirstTouchScreenPoint(aEvent);
|
||||
float dx = mX.PanDistance(point.x);
|
||||
float dy = mY.PanDistance(point.y);
|
||||
|
||||
// When the touch move breaks through the pan threshold, reposition the touch down origin
|
||||
// so the page won't jump when we start panning.
|
||||
mX.StartTouch(point.x);
|
||||
mY.StartTouch(point.y);
|
||||
mLastEventTime = aEvent.mTime;
|
||||
|
||||
if (GetAxisLockMode() == FREE) {
|
||||
SetState(PANNING);
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
double angle = atan2(dy, dx); // range [-pi, pi]
|
||||
angle = fabs(angle); // range [0, pi]
|
||||
|
||||
SetState(PANNING);
|
||||
if (!gCrossSlideEnabled && (!mX.Scrollable() || !mY.Scrollable())) {
|
||||
SetState(PANNING);
|
||||
} else if (IsCloseToHorizontal(angle, AXIS_LOCK_ANGLE)) {
|
||||
mY.SetScrollingDisabled(true);
|
||||
if (mX.Scrollable()) {
|
||||
SetState(PANNING_LOCKED_X);
|
||||
} else {
|
||||
SetState(CROSS_SLIDING_X);
|
||||
mX.SetScrollingDisabled(true);
|
||||
}
|
||||
} else if (IsCloseToVertical(angle, AXIS_LOCK_ANGLE)) {
|
||||
mX.SetScrollingDisabled(true);
|
||||
if (mY.Scrollable()) {
|
||||
SetState(PANNING_LOCKED_Y);
|
||||
} else {
|
||||
SetState(CROSS_SLIDING_Y);
|
||||
mY.SetScrollingDisabled(true);
|
||||
}
|
||||
} else {
|
||||
SetState(PANNING);
|
||||
}
|
||||
|
||||
// Don't consume an event that starts a cross-slide.
|
||||
return IsPanningState(mState) ? nsEventStatus_eConsumeNoDefault
|
||||
: nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent) {
|
||||
SingleTouchData& touch = GetFirstSingleTouch(aEvent);
|
||||
ScreenIntPoint point = touch.mScreenPoint;
|
||||
ScreenIntPoint point = GetFirstTouchScreenPoint(aEvent);
|
||||
TimeDuration timeDelta = TimeDuration().FromMilliseconds(aEvent.mTime - mLastEventTime);
|
||||
|
||||
// Probably a duplicate event, just throw it away.
|
||||
|
@ -769,9 +868,8 @@ void AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
|||
}
|
||||
|
||||
void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
|
||||
SingleTouchData& touch = GetFirstSingleTouch(aEvent);
|
||||
ScreenIntPoint prevTouchPoint(mX.GetPos(), mY.GetPos());
|
||||
ScreenIntPoint touchPoint = touch.mScreenPoint;
|
||||
ScreenIntPoint touchPoint = GetFirstTouchScreenPoint(aEvent);
|
||||
TimeDuration timeDelta = TimeDuration().FromMilliseconds(aEvent.mTime - mLastEventTime);
|
||||
|
||||
// Probably a duplicate event, just throw it away.
|
||||
|
@ -779,13 +877,39 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
|
|||
return;
|
||||
}
|
||||
|
||||
// If we're axis-locked, check if the user is trying to break the lock
|
||||
if (GetAxisLockMode() == STICKY) {
|
||||
ScreenIntPoint point = GetFirstTouchScreenPoint(aEvent);
|
||||
float dx = mX.PanDistance(point.x);
|
||||
float dy = mY.PanDistance(point.y);
|
||||
|
||||
double angle = atan2(dy, dx); // range [-pi, pi]
|
||||
angle = fabs(angle); // range [0, pi]
|
||||
|
||||
float breakThreshold = AXIS_BREAKOUT_THRESHOLD * APZCTreeManager::GetDPI();
|
||||
|
||||
if (fabs(dx) > breakThreshold || fabs(dy) > breakThreshold) {
|
||||
if (mState == PANNING_LOCKED_X || mState == CROSS_SLIDING_X) {
|
||||
if (!IsCloseToHorizontal(angle, AXIS_BREAKOUT_ANGLE)) {
|
||||
mY.SetScrollingDisabled(false);
|
||||
SetState(PANNING);
|
||||
}
|
||||
} else if (mState == PANNING_LOCKED_Y || mState == CROSS_SLIDING_Y) {
|
||||
if (!IsCloseToVertical(angle, AXIS_BREAKOUT_ANGLE)) {
|
||||
mX.SetScrollingDisabled(false);
|
||||
SetState(PANNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateWithTouchAtDevicePoint(aEvent);
|
||||
|
||||
AttemptScroll(prevTouchPoint, touchPoint);
|
||||
}
|
||||
|
||||
SingleTouchData& AsyncPanZoomController::GetFirstSingleTouch(const MultiTouchInput& aEvent) {
|
||||
return (SingleTouchData&)aEvent.mTouches[0];
|
||||
ScreenIntPoint& AsyncPanZoomController::GetFirstTouchScreenPoint(const MultiTouchInput& aEvent) {
|
||||
return ((SingleTouchData&)aEvent.mTouches[0]).mScreenPoint;
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::DoFling(const TimeDuration& aDelta) {
|
||||
|
@ -1365,14 +1489,18 @@ void AsyncPanZoomController::SetState(PanZoomState aNewState) {
|
|||
}
|
||||
|
||||
if (mGeckoContentController) {
|
||||
if (oldState == PANNING && aNewState != PANNING) {
|
||||
if (IsPanningState(oldState) && !IsPanningState(aNewState)) {
|
||||
mGeckoContentController->HandlePanEnd();
|
||||
} else if (oldState != PANNING && aNewState == PANNING) {
|
||||
} else if (!IsPanningState(oldState) && IsPanningState(aNewState)) {
|
||||
mGeckoContentController->HandlePanBegin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::IsPanningState(PanZoomState aState) {
|
||||
return (aState == PANNING || aState == PANNING_LOCKED_X || aState == PANNING_LOCKED_Y);
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::TimeoutTouchListeners() {
|
||||
mTouchListenerTimeoutTask = nullptr;
|
||||
ContentReceivedTouch(false);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* 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/. */
|
||||
|
@ -391,17 +391,17 @@ protected:
|
|||
const gfx::Point GetAccelerationVector();
|
||||
|
||||
/**
|
||||
* Gets a reference to the first SingleTouchData from a MultiTouchInput. This
|
||||
* Gets a reference to the first touch point from a MultiTouchInput. This
|
||||
* gets only the first one and assumes the rest are either missing or not
|
||||
* relevant.
|
||||
*/
|
||||
SingleTouchData& GetFirstSingleTouch(const MultiTouchInput& aEvent);
|
||||
ScreenIntPoint& GetFirstTouchScreenPoint(const MultiTouchInput& aEvent);
|
||||
|
||||
/**
|
||||
* Sets up anything needed for panning. This takes us out of the "TOUCHING"
|
||||
* state and starts actually panning us.
|
||||
*/
|
||||
void StartPanning(const MultiTouchInput& aStartPoint);
|
||||
nsEventStatus StartPanning(const MultiTouchInput& aStartPoint);
|
||||
|
||||
/**
|
||||
* Wrapper for Axis::UpdateWithTouchAtDevicePoint(). Calls this function for
|
||||
|
@ -484,7 +484,16 @@ private:
|
|||
NOTHING, /* no touch-start events received */
|
||||
FLING, /* all touches removed, but we're still scrolling page */
|
||||
TOUCHING, /* one touch-start event received */
|
||||
PANNING, /* panning the frame */
|
||||
|
||||
PANNING, /* panning the frame */
|
||||
PANNING_LOCKED_X, /* touch-start followed by move (i.e. panning with axis lock) X axis */
|
||||
PANNING_LOCKED_Y, /* as above for Y axis */
|
||||
|
||||
CROSS_SLIDING_X, /* Panning disabled while user does a horizontal gesture
|
||||
on a vertically-scrollable view. This used for the
|
||||
Windows Metro "cross-slide" gesture. */
|
||||
CROSS_SLIDING_Y, /* as above for Y axis */
|
||||
|
||||
PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */
|
||||
ANIMATING_ZOOM, /* animated zoom to a new rect */
|
||||
WAITING_LISTENERS, /* a state halfway between NOTHING and TOUCHING - the user has
|
||||
|
@ -492,6 +501,14 @@ private:
|
|||
prevented the default actions yet. we still need to abort animations. */
|
||||
};
|
||||
|
||||
enum AxisLockMode {
|
||||
FREE, /* No locking at all */
|
||||
STANDARD, /* Default axis locking mode that remains locked until pan ends*/
|
||||
STICKY, /* Allow lock to be broken, with hysteresis */
|
||||
};
|
||||
|
||||
static AxisLockMode GetAxisLockMode();
|
||||
|
||||
/**
|
||||
* Helper to set the current state. Holds the monitor before actually setting
|
||||
* it. If the monitor is already held by the current thread, it is safe to
|
||||
|
@ -499,6 +516,8 @@ private:
|
|||
*/
|
||||
void SetState(PanZoomState aState);
|
||||
|
||||
bool IsPanningState(PanZoomState mState);
|
||||
|
||||
uint64_t mLayersId;
|
||||
nsRefPtr<CompositorParent> mCompositorParent;
|
||||
TaskThrottler mPaintThrottler;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* 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/. */
|
||||
|
@ -103,13 +103,14 @@ Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
|
|||
: mPos(0),
|
||||
mVelocity(0.0f),
|
||||
mAcceleration(0),
|
||||
mScrollingDisabled(false),
|
||||
mAsyncPanZoomController(aAsyncPanZoomController)
|
||||
{
|
||||
InitAxisPrefs();
|
||||
}
|
||||
|
||||
void Axis::UpdateWithTouchAtDevicePoint(int32_t aPos, const TimeDuration& aTimeDelta) {
|
||||
float newVelocity = (mPos - aPos) / aTimeDelta.ToMilliseconds();
|
||||
float newVelocity = mScrollingDisabled ? 0 : (mPos - aPos) / aTimeDelta.ToMilliseconds();
|
||||
|
||||
bool curVelocityBelowThreshold = fabsf(newVelocity) < gVelocityThreshold;
|
||||
bool directionChange = (mVelocity > 0) != (newVelocity > 0);
|
||||
|
@ -133,9 +134,15 @@ void Axis::UpdateWithTouchAtDevicePoint(int32_t aPos, const TimeDuration& aTimeD
|
|||
void Axis::StartTouch(int32_t aPos) {
|
||||
mStartPos = aPos;
|
||||
mPos = aPos;
|
||||
mScrollingDisabled = false;
|
||||
}
|
||||
|
||||
float Axis::AdjustDisplacement(float aDisplacement, float& aOverscrollAmountOut) {
|
||||
if (mScrollingDisabled) {
|
||||
aOverscrollAmountOut = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fabsf(mVelocity) < gVelocityThreshold) {
|
||||
mAcceleration = 0;
|
||||
}
|
||||
|
@ -159,6 +166,10 @@ float Axis::PanDistance() {
|
|||
return fabsf(mPos - mStartPos);
|
||||
}
|
||||
|
||||
float Axis::PanDistance(float aPos) {
|
||||
return fabsf(aPos - mStartPos);
|
||||
}
|
||||
|
||||
void Axis::EndTouch() {
|
||||
mAcceleration++;
|
||||
|
||||
|
@ -182,6 +193,13 @@ void Axis::CancelTouch() {
|
|||
}
|
||||
}
|
||||
|
||||
bool Axis::Scrollable() {
|
||||
if (mScrollingDisabled) {
|
||||
return false;
|
||||
}
|
||||
return GetCompositionLength() < GetPageLength();
|
||||
}
|
||||
|
||||
bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta) {
|
||||
if (fabsf(mVelocity) <= gFlingStoppedThreshold) {
|
||||
// If the velocity is very low, just set it to 0 and stop the fling,
|
||||
|
@ -284,7 +302,7 @@ float Axis::ScaleWillOverscrollAmount(ScreenToScreenScale aScale, float aFocus)
|
|||
}
|
||||
|
||||
float Axis::GetVelocity() {
|
||||
return mVelocity;
|
||||
return mScrollingDisabled ? 0 : mVelocity;
|
||||
}
|
||||
|
||||
float Axis::GetAccelerationFactor() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 : */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* 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/. */
|
||||
|
@ -69,10 +69,11 @@ public:
|
|||
|
||||
/**
|
||||
* Takes a requested displacement to the position of this axis, and adjusts
|
||||
* it to account for acceleration (which might increase the displacement)
|
||||
* and overscroll (which might decrease the displacement; this is to prevent
|
||||
* the viewport from overscrolling the page rect). If overscroll ocurred,
|
||||
* its amount is written to |aOverscrollAmountOut|.
|
||||
* it to account for acceleration (which might increase the displacement),
|
||||
* overscroll (which might decrease the displacement; this is to prevent the
|
||||
* viewport from overscrolling the page rect), and axis locking (which might
|
||||
* prevent any displacement from happening). If overscroll ocurred, its amount
|
||||
* is written to |aOverscrollAmountOut|.
|
||||
* The adjusted displacement is returned.
|
||||
*/
|
||||
float AdjustDisplacement(float aDisplacement, float& aOverscrollAmountOut);
|
||||
|
@ -84,6 +85,12 @@ public:
|
|||
*/
|
||||
float PanDistance();
|
||||
|
||||
/**
|
||||
* Gets the distance between the starting position of the touch supplied in
|
||||
* startTouch() and the supplied position.
|
||||
*/
|
||||
float PanDistance(float aPos);
|
||||
|
||||
/**
|
||||
* Applies friction during a fling, or cancels the fling if the velocity is
|
||||
* too low. Returns true if the fling should continue to another frame, or
|
||||
|
@ -92,6 +99,14 @@ public:
|
|||
*/
|
||||
bool FlingApplyFrictionOrCancel(const TimeDuration& aDelta);
|
||||
|
||||
/*
|
||||
* Returns true if the page is zoomed in to some degree along this axis such that scrolling is
|
||||
* possible and this axis has not been scroll locked while panning. Otherwise, returns false.
|
||||
*/
|
||||
bool Scrollable();
|
||||
|
||||
void SetScrollingDisabled(bool aDisabled) { mScrollingDisabled = aDisabled; }
|
||||
|
||||
/**
|
||||
* Gets the overscroll state of the axis in its current position.
|
||||
*/
|
||||
|
@ -184,6 +199,7 @@ protected:
|
|||
// they are flinging multiple times in a row very quickly, probably trying to
|
||||
// reach one of the extremes of the page.
|
||||
int32_t mAcceleration;
|
||||
bool mScrollingDisabled; // Whether movement on this axis is locked.
|
||||
AsyncPanZoomController* mAsyncPanZoomController;
|
||||
nsTArray<float> mVelocityQueue;
|
||||
};
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.prompts.Prompt;
|
||||
import org.mozilla.gecko.prompts.PromptService;
|
||||
import org.mozilla.gecko.util.ActivityResultHandler;
|
||||
import org.mozilla.gecko.util.ActivityResultHandlerMap;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.mozilla.gecko;
|
|||
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.prompts.PromptService;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.mozilla.gecko.home.BrowserSearch;
|
|||
import org.mozilla.gecko.home.HomePager;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
import org.mozilla.gecko.menu.GeckoMenu;
|
||||
import org.mozilla.gecko.prompts.Prompt;
|
||||
import org.mozilla.gecko.util.Clipboard;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.widget.Divider;
|
||||
import org.mozilla.gecko.prompts.PromptInput;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.mozilla.gecko;
|
|||
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.widget.ArrowPopup;
|
||||
import org.mozilla.gecko.prompts.PromptInput;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.mozilla.gecko.gfx.BitmapUtils;
|
|||
import org.mozilla.gecko.gfx.Layer;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.PluginLayer;
|
||||
import org.mozilla.gecko.prompts.PromptService;
|
||||
import org.mozilla.gecko.menu.GeckoMenu;
|
||||
import org.mozilla.gecko.menu.GeckoMenuInflater;
|
||||
import org.mozilla.gecko.menu.MenuPanel;
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.mozilla.gecko.gfx.GeckoLayerClient;
|
|||
import org.mozilla.gecko.gfx.GfxInfoThread;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.PanZoomController;
|
||||
import org.mozilla.gecko.prompts.PromptService;
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
import org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget;
|
||||
import org.mozilla.gecko.mozglue.OptionalGeneratedParameter;
|
||||
|
|
|
@ -126,9 +126,9 @@ FENNEC_JAVA_FILES = \
|
|||
PrefsHelper.java \
|
||||
PrivateDataPreference.java \
|
||||
PrivateTab.java \
|
||||
Prompt.java \
|
||||
PromptInput.java \
|
||||
PromptService.java \
|
||||
prompts/Prompt.java \
|
||||
prompts/PromptInput.java \
|
||||
prompts/PromptService.java \
|
||||
Restarter.java \
|
||||
sqlite/ByteBufferInputStream.java \
|
||||
sqlite/MatrixBlobCursor.java \
|
||||
|
|
|
@ -62,17 +62,6 @@ public class BookmarksListView extends HomeListView
|
|||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final ListView list = (ListView) parent;
|
||||
final int headerCount = list.getHeaderViewsCount();
|
||||
|
||||
if (position < headerCount) {
|
||||
// The click is on a header, don't do anything.
|
||||
return;
|
||||
}
|
||||
|
||||
// Absolute position for the adapter.
|
||||
position -= headerCount;
|
||||
|
||||
final BookmarksListAdapter adapter = getBookmarksListAdapter();
|
||||
if (adapter.isShowingChildFolder()) {
|
||||
if (position == 0) {
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
package org.mozilla.gecko.prompts;
|
||||
|
||||
import org.mozilla.gecko.util.GeckoEventResponder;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.widget.DateTimePicker;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
|
@ -3,8 +3,9 @@
|
|||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
package org.mozilla.gecko.prompts;
|
||||
|
||||
import org.mozilla.gecko.AllCapsTextView;
|
||||
import org.mozilla.gecko.util.GeckoEventResponder;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.widget.DateTimePicker;
|
||||
|
@ -40,7 +41,7 @@ import java.util.GregorianCalendar;
|
|||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
class PromptInput {
|
||||
public class PromptInput {
|
||||
private final JSONObject mJSONInput;
|
||||
|
||||
protected final String mLabel;
|
|
@ -3,8 +3,10 @@
|
|||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
package org.mozilla.gecko.prompts;
|
||||
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.util.GeckoEventResponder;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
|
@ -27,7 +29,7 @@ public class PromptService implements GeckoEventResponder {
|
|||
mContext = context;
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
public void destroy() {
|
||||
GeckoAppShell.getEventDispatcher().unregisterEventListener("Prompt:Show", this);
|
||||
GeckoAppShell.getEventDispatcher().unregisterEventListener("Prompt:ShowTop", this);
|
||||
}
|
|
@ -64,7 +64,7 @@ public class FaviconView extends ImageView {
|
|||
private void formatImage() {
|
||||
// If we're called before bitmap is set, or before size is set, show blank.
|
||||
if (mIconBitmap == null || mActualWidth == 0 || mActualHeight == 0) {
|
||||
clearImage();
|
||||
showNoImage();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -157,12 +157,16 @@ public class FaviconView extends ImageView {
|
|||
hideBackground();
|
||||
}
|
||||
|
||||
private void showNoImage() {
|
||||
setImageBitmap(null);
|
||||
hideBackground();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear image and background shown by this view.
|
||||
*/
|
||||
public void clearImage() {
|
||||
setImageResource(0);
|
||||
hideBackground();
|
||||
showNoImage();
|
||||
mUnscaledBitmap = null;
|
||||
mIconBitmap = null;
|
||||
mIconKey = null;
|
||||
|
|
|
@ -519,7 +519,7 @@ body {
|
|||
background-image: url('chrome://browser/skin/images/reader-style-icon-mdpi.png');
|
||||
}
|
||||
|
||||
@media screen and (min-resolution: 200dpi) {
|
||||
@media screen and (min-resolution: 1.25dppx) {
|
||||
.dropdown-arrow {
|
||||
background-image: url('chrome://browser/skin/images/reader-dropdown-arrow-hdpi.png');
|
||||
}
|
||||
|
@ -557,7 +557,7 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
@media screen and (min-resolution: 300dpi) {
|
||||
@media screen and (min-resolution: 2dppx) {
|
||||
.dropdown-arrow {
|
||||
background-image: url('chrome://browser/skin/images/reader-dropdown-arrow-xhdpi.png');
|
||||
}
|
||||
|
|
|
@ -276,6 +276,12 @@ pref("media.video_stats.enabled", true);
|
|||
// Whether to enable the audio writing APIs on the audio element
|
||||
pref("media.audio_data.enabled", true);
|
||||
|
||||
// Whether to lock touch scrolling to one axis at a time
|
||||
// 0 = FREE (No locking at all)
|
||||
// 1 = STANDARD (Once locked, remain locked until scrolling ends)
|
||||
// 2 = STICKY (Allow lock to be broken, with hysteresis)
|
||||
pref("apzc.axis_lock_mode", 0);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Whether to run in native HiDPI mode on machines with "Retina"/HiDPI display;
|
||||
// <= 0 : hidpi mode disabled, display will just use pixel-based upscaling
|
||||
|
|
Загрузка…
Ссылка в новой задаче