зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 77fdb4380b1a (bug 938359) for metro-chrome bustage on a CLOSED TREE
This commit is contained in:
Родитель
3b2c162aeb
Коммит
4e8b21430c
|
@ -8,7 +8,6 @@ let Ci = Components.interfaces;
|
||||||
let Cu = Components.utils;
|
let Cu = Components.utils;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "ContentLinkHandler",
|
XPCOMUtils.defineLazyModuleGetter(this, "ContentLinkHandler",
|
||||||
"resource:///modules/ContentLinkHandler.jsm");
|
"resource:///modules/ContentLinkHandler.jsm");
|
||||||
|
|
|
@ -1,234 +0,0 @@
|
||||||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
let Cc = Components.classes;
|
|
||||||
let Ci = Components.interfaces;
|
|
||||||
let Cu = Components.utils;
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
var global = this;
|
|
||||||
|
|
||||||
let ClickEventHandler = {
|
|
||||||
init: function init() {
|
|
||||||
this._scrollable = null;
|
|
||||||
this._scrolldir = "";
|
|
||||||
this._startX = null;
|
|
||||||
this._startY = null;
|
|
||||||
this._screenX = null;
|
|
||||||
this._screenY = null;
|
|
||||||
this._lastFrame = null;
|
|
||||||
|
|
||||||
Cc["@mozilla.org/eventlistenerservice;1"]
|
|
||||||
.getService(Ci.nsIEventListenerService)
|
|
||||||
.addSystemEventListener(global, "mousedown", this, true);
|
|
||||||
|
|
||||||
addMessageListener("Autoscroll:Stop", this);
|
|
||||||
},
|
|
||||||
|
|
||||||
isAutoscrollBlocker: function(node) {
|
|
||||||
let mmPaste = Services.prefs.getBoolPref("middlemouse.paste");
|
|
||||||
let mmScrollbarPosition = Services.prefs.getBoolPref("middlemouse.scrollbarPosition");
|
|
||||||
|
|
||||||
while (node) {
|
|
||||||
if ((node instanceof content.HTMLAnchorElement || node instanceof content.HTMLAreaElement) &&
|
|
||||||
node.hasAttribute("href")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mmPaste && (node instanceof content.HTMLInputElement ||
|
|
||||||
node instanceof content.HTMLTextAreaElement)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node instanceof content.XULElement && mmScrollbarPosition
|
|
||||||
&& (node.localName == "scrollbar" || node.localName == "scrollcorner")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = node.parentNode;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
startScroll: function(event) {
|
|
||||||
// this is a list of overflow property values that allow scrolling
|
|
||||||
const scrollingAllowed = ['scroll', 'auto'];
|
|
||||||
|
|
||||||
// go upward in the DOM and find any parent element that has a overflow
|
|
||||||
// area and can therefore be scrolled
|
|
||||||
for (this._scrollable = event.originalTarget; this._scrollable;
|
|
||||||
this._scrollable = this._scrollable.parentNode) {
|
|
||||||
// do not use overflow based autoscroll for <html> and <body>
|
|
||||||
// Elements or non-html elements such as svg or Document nodes
|
|
||||||
// also make sure to skip select elements that are not multiline
|
|
||||||
if (!(this._scrollable instanceof content.HTMLElement) ||
|
|
||||||
((this._scrollable instanceof content.HTMLSelectElement) && !this._scrollable.multiple)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var overflowx = this._scrollable.ownerDocument.defaultView
|
|
||||||
.getComputedStyle(this._scrollable, '')
|
|
||||||
.getPropertyValue('overflow-x');
|
|
||||||
var overflowy = this._scrollable.ownerDocument.defaultView
|
|
||||||
.getComputedStyle(this._scrollable, '')
|
|
||||||
.getPropertyValue('overflow-y');
|
|
||||||
// we already discarded non-multiline selects so allow vertical
|
|
||||||
// scroll for multiline ones directly without checking for a
|
|
||||||
// overflow property
|
|
||||||
var scrollVert = this._scrollable.scrollTopMax &&
|
|
||||||
(this._scrollable instanceof content.HTMLSelectElement ||
|
|
||||||
scrollingAllowed.indexOf(overflowy) >= 0);
|
|
||||||
|
|
||||||
// do not allow horizontal scrolling for select elements, it leads
|
|
||||||
// to visual artifacts and is not the expected behavior anyway
|
|
||||||
if (!(this._scrollable instanceof content.HTMLSelectElement) &&
|
|
||||||
this._scrollable.scrollLeftMax &&
|
|
||||||
scrollingAllowed.indexOf(overflowx) >= 0) {
|
|
||||||
this._scrolldir = scrollVert ? "NSEW" : "EW";
|
|
||||||
break;
|
|
||||||
} else if (scrollVert) {
|
|
||||||
this._scrolldir = "NS";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._scrollable) {
|
|
||||||
this._scrollable = event.originalTarget.ownerDocument.defaultView;
|
|
||||||
if (this._scrollable.scrollMaxX > 0) {
|
|
||||||
this._scrolldir = this._scrollable.scrollMaxY > 0 ? "NSEW" : "EW";
|
|
||||||
} else if (this._scrollable.scrollMaxY > 0) {
|
|
||||||
this._scrolldir = "NS";
|
|
||||||
} else {
|
|
||||||
this._scrollable = null; // abort scrolling
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Cc["@mozilla.org/eventlistenerservice;1"]
|
|
||||||
.getService(Ci.nsIEventListenerService)
|
|
||||||
.addSystemEventListener(global, "mousemove", this, true);
|
|
||||||
addEventListener("pagehide", this, true);
|
|
||||||
|
|
||||||
sendAsyncMessage("Autoscroll:Start", {scrolldir: this._scrolldir,
|
|
||||||
screenX: event.screenX,
|
|
||||||
screenY: event.screenY});
|
|
||||||
this._ignoreMouseEvents = true;
|
|
||||||
this._startX = event.screenX;
|
|
||||||
this._startY = event.screenY;
|
|
||||||
this._screenX = event.screenX;
|
|
||||||
this._screenY = event.screenY;
|
|
||||||
this._scrollErrorX = 0;
|
|
||||||
this._scrollErrorY = 0;
|
|
||||||
this._lastFrame = content.mozAnimationStartTime;
|
|
||||||
|
|
||||||
content.mozRequestAnimationFrame(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
stopScroll: function() {
|
|
||||||
if (this._scrollable) {
|
|
||||||
this._scrollable = null;
|
|
||||||
|
|
||||||
Cc["@mozilla.org/eventlistenerservice;1"]
|
|
||||||
.getService(Ci.nsIEventListenerService)
|
|
||||||
.removeSystemEventListener(global, "mousemove", this, true);
|
|
||||||
removeEventListener("pagehide", this, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
accelerate: function(curr, start) {
|
|
||||||
const speed = 12;
|
|
||||||
var val = (curr - start) / speed;
|
|
||||||
|
|
||||||
if (val > 1)
|
|
||||||
return val * Math.sqrt(val) - 1;
|
|
||||||
if (val < -1)
|
|
||||||
return val * Math.sqrt(-val) + 1;
|
|
||||||
return 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
roundToZero: function(num) {
|
|
||||||
if (num > 0)
|
|
||||||
return Math.floor(num);
|
|
||||||
return Math.ceil(num);
|
|
||||||
},
|
|
||||||
|
|
||||||
autoscrollLoop: function(timestamp) {
|
|
||||||
if (!this._scrollable) {
|
|
||||||
// Scrolling has been canceled
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// avoid long jumps when the browser hangs for more than
|
|
||||||
// |maxTimeDelta| ms
|
|
||||||
const maxTimeDelta = 100;
|
|
||||||
var timeDelta = Math.min(maxTimeDelta, timestamp - this._lastFrame);
|
|
||||||
// we used to scroll |accelerate()| pixels every 20ms (50fps)
|
|
||||||
var timeCompensation = timeDelta / 20;
|
|
||||||
this._lastFrame = timestamp;
|
|
||||||
|
|
||||||
var actualScrollX = 0;
|
|
||||||
var actualScrollY = 0;
|
|
||||||
// don't bother scrolling vertically when the scrolldir is only horizontal
|
|
||||||
// and the other way around
|
|
||||||
if (this._scrolldir != 'EW') {
|
|
||||||
var y = this.accelerate(this._screenY, this._startY) * timeCompensation;
|
|
||||||
var desiredScrollY = this._scrollErrorY + y;
|
|
||||||
actualScrollY = this.roundToZero(desiredScrollY);
|
|
||||||
this._scrollErrorY = (desiredScrollY - actualScrollY);
|
|
||||||
}
|
|
||||||
if (this._scrolldir != 'NS') {
|
|
||||||
var x = this.accelerate(this._screenX, this._startX) * timeCompensation;
|
|
||||||
var desiredScrollX = this._scrollErrorX + x;
|
|
||||||
actualScrollX = this.roundToZero(desiredScrollX);
|
|
||||||
this._scrollErrorX = (desiredScrollX - actualScrollX);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._scrollable instanceof content.Window) {
|
|
||||||
this._scrollable.scrollBy(actualScrollX, actualScrollY);
|
|
||||||
} else { // an element with overflow
|
|
||||||
this._scrollable.scrollLeft += actualScrollX;
|
|
||||||
this._scrollable.scrollTop += actualScrollY;
|
|
||||||
}
|
|
||||||
content.mozRequestAnimationFrame(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
sample: function(timestamp) {
|
|
||||||
this.autoscrollLoop(timestamp);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleEvent: function(event) {
|
|
||||||
if (event.type == "mousemove") {
|
|
||||||
this._screenX = event.screenX;
|
|
||||||
this._screenY = event.screenY;
|
|
||||||
} else if (event.type == "mousedown") {
|
|
||||||
if (event.isTrusted &
|
|
||||||
!event.defaultPrevented &&
|
|
||||||
event.button == 1 &&
|
|
||||||
!this._scrollable &&
|
|
||||||
!this.isAutoscrollBlocker(event.originalTarget)) {
|
|
||||||
this.startScroll(event);
|
|
||||||
}
|
|
||||||
} else if (event.type == "pagehide") {
|
|
||||||
if (this._scrollable) {
|
|
||||||
var doc =
|
|
||||||
this._scrollable.ownerDocument || this._scrollable.document;
|
|
||||||
if (doc == event.target) {
|
|
||||||
sendAsyncMessage("Autoscroll:Cancel");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
receiveMessage: function(msg) {
|
|
||||||
switch (msg.name) {
|
|
||||||
case "Autoscroll:Stop": {
|
|
||||||
this.stopScroll();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
ClickEventHandler.init();
|
|
|
@ -28,7 +28,6 @@ toolkit.jar:
|
||||||
content/global/plugins.html
|
content/global/plugins.html
|
||||||
content/global/plugins.css
|
content/global/plugins.css
|
||||||
content/global/browser-child.js (browser-child.js)
|
content/global/browser-child.js (browser-child.js)
|
||||||
content/global/browser-content.js (browser-content.js)
|
|
||||||
*+ content/global/buildconfig.html (buildconfig.html)
|
*+ content/global/buildconfig.html (buildconfig.html)
|
||||||
+ content/global/charsetOverlay.js (charsetOverlay.js)
|
+ content/global/charsetOverlay.js (charsetOverlay.js)
|
||||||
+ content/global/charsetOverlay.xul (charsetOverlay.xul)
|
+ content/global/charsetOverlay.xul (charsetOverlay.xul)
|
||||||
|
|
|
@ -75,10 +75,7 @@ function test()
|
||||||
ok((scrollHori && elem.scrollLeft > 0) ||
|
ok((scrollHori && elem.scrollLeft > 0) ||
|
||||||
(!scrollHori && elem.scrollLeft == 0),
|
(!scrollHori && elem.scrollLeft == 0),
|
||||||
test.elem+' should'+(scrollHori ? '' : ' not')+' have scrolled horizontally');
|
test.elem+' should'+(scrollHori ? '' : ' not')+' have scrolled horizontally');
|
||||||
|
nextTest();
|
||||||
// Before continuing the test, we need to ensure that the IPC
|
|
||||||
// message that stops autoscrolling has had time to arrive.
|
|
||||||
executeSoon(nextTest);
|
|
||||||
};
|
};
|
||||||
EventUtils.synthesizeMouse(elem, 50, 50, { button: 1 },
|
EventUtils.synthesizeMouse(elem, 50, 50, { button: 1 },
|
||||||
gBrowser.contentWindow);
|
gBrowser.contentWindow);
|
||||||
|
|
|
@ -90,12 +90,6 @@ function test()
|
||||||
EventUtils.synthesizeMouse(root, 10, 10, { button: 1 },
|
EventUtils.synthesizeMouse(root, 10, 10, { button: 1 },
|
||||||
gBrowser.contentWindow);
|
gBrowser.contentWindow);
|
||||||
|
|
||||||
// Before continuing the test, we need to ensure that the IPC
|
|
||||||
// message that starts autoscrolling has had time to arrive.
|
|
||||||
executeSoon(continueTest);
|
|
||||||
}
|
|
||||||
|
|
||||||
function continueTest() {
|
|
||||||
// Most key events should be eaten by the browser.
|
// Most key events should be eaten by the browser.
|
||||||
expectedKeyEvents = kNoKeyEvents;
|
expectedKeyEvents = kNoKeyEvents;
|
||||||
sendChar("A");
|
sendChar("A");
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<content clickthrough="never">
|
<content clickthrough="never">
|
||||||
<children/>
|
<children/>
|
||||||
</content>
|
</content>
|
||||||
<implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIFrameRequestCallback, nsIMessageListener">
|
<implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIFrameRequestCallback">
|
||||||
<property name="autoscrollEnabled">
|
<property name="autoscrollEnabled">
|
||||||
<getter>
|
<getter>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
|
@ -600,6 +600,14 @@
|
||||||
if (!tabBrowser || !("fastFind" in tabBrowser) ||
|
if (!tabBrowser || !("fastFind" in tabBrowser) ||
|
||||||
tabBrowser.selectedBrowser == this)
|
tabBrowser.selectedBrowser == this)
|
||||||
this.fastFind.setDocShell(this.docShell);
|
this.fastFind.setDocShell(this.docShell);
|
||||||
|
|
||||||
|
if (this._scrollable) {
|
||||||
|
var doc =
|
||||||
|
this._scrollable.ownerDocument || this._scrollable.document;
|
||||||
|
if (doc == aEvent.target) {
|
||||||
|
this._autoScrollPopup.hidePopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
@ -785,12 +793,6 @@
|
||||||
this.addEventListener("pageshow", this.onPageShow, true);
|
this.addEventListener("pageshow", this.onPageShow, true);
|
||||||
this.addEventListener("pagehide", this.onPageHide, true);
|
this.addEventListener("pagehide", this.onPageHide, true);
|
||||||
this.addEventListener("DOMPopupBlocked", this.onPopupBlocked, true);
|
this.addEventListener("DOMPopupBlocked", this.onPopupBlocked, true);
|
||||||
|
|
||||||
if (this.messageManager) {
|
|
||||||
this.messageManager.addMessageListener("Autoscroll:Start", this);
|
|
||||||
this.messageManager.addMessageListener("Autoscroll:Cancel", this);
|
|
||||||
this.messageManager.loadFrameScript("chrome://global/content/browser-content.js", true);
|
|
||||||
}
|
|
||||||
]]>
|
]]>
|
||||||
</constructor>
|
</constructor>
|
||||||
|
|
||||||
|
@ -841,34 +843,6 @@
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<!--
|
|
||||||
We call this _receiveMessage (and alias receiveMessage to it) so that
|
|
||||||
bindings that inherit from this one can delegate to it.
|
|
||||||
-->
|
|
||||||
<method name="_receiveMessage">
|
|
||||||
<parameter name="aMessage"/>
|
|
||||||
<body><![CDATA[
|
|
||||||
let data = aMessage.data;
|
|
||||||
switch (aMessage.name) {
|
|
||||||
case "Autoscroll:Start": {
|
|
||||||
let pos = this.mapScreenCoordinatesFromContent(data.screenX, data.screenY);
|
|
||||||
this.startScroll(data.scrolldir, pos.x, pos.y);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "Autoscroll:Cancel":
|
|
||||||
this._autoScrollPopup.hidePopup();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
]]></body>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<method name="receiveMessage">
|
|
||||||
<parameter name="aMessage"/>
|
|
||||||
<body><![CDATA[
|
|
||||||
return this._receiveMessage(aMessage);
|
|
||||||
]]></body>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<method name="observe">
|
<method name="observe">
|
||||||
<parameter name="aSubject"/>
|
<parameter name="aSubject"/>
|
||||||
<parameter name="aTopic"/>
|
<parameter name="aTopic"/>
|
||||||
|
@ -897,17 +871,20 @@
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<field name="_AUTOSCROLL_SNAP">10</field>
|
<field name="_AUTOSCROLL_SNAP">10</field>
|
||||||
<field name="_scrolling">false</field>
|
<field name="_scrollable">null</field>
|
||||||
<field name="_startX">null</field>
|
<field name="_startX">null</field>
|
||||||
<field name="_startY">null</field>
|
<field name="_startY">null</field>
|
||||||
|
<field name="_screenX">null</field>
|
||||||
|
<field name="_screenY">null</field>
|
||||||
|
<field name="_lastFrame">null</field>
|
||||||
<field name="_autoScrollPopup">null</field>
|
<field name="_autoScrollPopup">null</field>
|
||||||
<field name="_autoScrollNeedsCleanup">false</field>
|
<field name="_autoScrollNeedsCleanup">false</field>
|
||||||
|
|
||||||
<method name="stopScroll">
|
<method name="stopScroll">
|
||||||
<body>
|
<body>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
if (this._scrolling) {
|
if (this._scrollable) {
|
||||||
this._scrolling = false;
|
this._scrollable = null;
|
||||||
window.removeEventListener("mousemove", this, true);
|
window.removeEventListener("mousemove", this, true);
|
||||||
window.removeEventListener("mousedown", this, true);
|
window.removeEventListener("mousedown", this, true);
|
||||||
window.removeEventListener("mouseup", this, true);
|
window.removeEventListener("mouseup", this, true);
|
||||||
|
@ -915,7 +892,6 @@
|
||||||
window.removeEventListener("keydown", this, true);
|
window.removeEventListener("keydown", this, true);
|
||||||
window.removeEventListener("keypress", this, true);
|
window.removeEventListener("keypress", this, true);
|
||||||
window.removeEventListener("keyup", this, true);
|
window.removeEventListener("keyup", this, true);
|
||||||
this.messageManager.sendAsyncMessage("Autoscroll:Stop");
|
|
||||||
}
|
}
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
|
@ -933,10 +909,9 @@
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<method name="startScroll">
|
<method name="startScroll">
|
||||||
<parameter name="scrolldir"/>
|
<parameter name="event"/>
|
||||||
<parameter name="screenX"/>
|
<body>
|
||||||
<parameter name="screenY"/>
|
<![CDATA[
|
||||||
<body><![CDATA[
|
|
||||||
if (!this._autoScrollPopup) {
|
if (!this._autoScrollPopup) {
|
||||||
if (this.hasAttribute("autoscrollpopup")) {
|
if (this.hasAttribute("autoscrollpopup")) {
|
||||||
// our creator provided a popup to share
|
// our creator provided a popup to share
|
||||||
|
@ -960,15 +935,74 @@
|
||||||
this._autoScrollPopup.setAttribute("translucent", /Win|Mac/.test(navigator.platform));
|
this._autoScrollPopup.setAttribute("translucent", /Win|Mac/.test(navigator.platform));
|
||||||
}
|
}
|
||||||
|
|
||||||
this._autoScrollPopup.setAttribute("scrolldir", scrolldir);
|
// this is a list of overflow property values that allow scrolling
|
||||||
|
const scrollingAllowed = ['scroll', 'auto'];
|
||||||
|
|
||||||
|
// go upward in the DOM and find any parent element that has a overflow
|
||||||
|
// area and can therefore be scrolled
|
||||||
|
for (this._scrollable = event.originalTarget; this._scrollable;
|
||||||
|
this._scrollable = this._scrollable.parentNode) {
|
||||||
|
// do not use overflow based autoscroll for <html> and <body>
|
||||||
|
// Elements or non-html elements such as svg or Document nodes
|
||||||
|
// also make sure to skip select elements that are not multiline
|
||||||
|
if (!(this._scrollable instanceof HTMLElement) ||
|
||||||
|
((this._scrollable instanceof HTMLSelectElement) && !this._scrollable.multiple)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var overflowx = this._scrollable.ownerDocument.defaultView
|
||||||
|
.getComputedStyle(this._scrollable, '')
|
||||||
|
.getPropertyValue('overflow-x');
|
||||||
|
var overflowy = this._scrollable.ownerDocument.defaultView
|
||||||
|
.getComputedStyle(this._scrollable, '')
|
||||||
|
.getPropertyValue('overflow-y');
|
||||||
|
// we already discarded non-multiline selects so allow vertical
|
||||||
|
// scroll for multiline ones directly without checking for a
|
||||||
|
// overflow property
|
||||||
|
var scrollVert = this._scrollable.scrollTopMax &&
|
||||||
|
(this._scrollable instanceof HTMLSelectElement ||
|
||||||
|
scrollingAllowed.indexOf(overflowy) >= 0);
|
||||||
|
|
||||||
|
// do not allow horizontal scrolling for select elements, it leads
|
||||||
|
// to visual artifacts and is not the expected behavior anyway
|
||||||
|
if (!(this._scrollable instanceof HTMLSelectElement) &&
|
||||||
|
this._scrollable.scrollLeftMax &&
|
||||||
|
scrollingAllowed.indexOf(overflowx) >= 0) {
|
||||||
|
this._autoScrollPopup.setAttribute("scrolldir", scrollVert ? "NSEW" : "EW");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (scrollVert) {
|
||||||
|
this._autoScrollPopup.setAttribute("scrolldir", "NS");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._scrollable) {
|
||||||
|
this._scrollable = event.originalTarget.ownerDocument.defaultView;
|
||||||
|
if (this._scrollable.scrollMaxX > 0) {
|
||||||
|
this._autoScrollPopup.setAttribute("scrolldir", this._scrollable.scrollMaxY > 0 ? "NSEW" : "EW");
|
||||||
|
}
|
||||||
|
else if (this._scrollable.scrollMaxY > 0) {
|
||||||
|
this._autoScrollPopup.setAttribute("scrolldir", "NS");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._scrollable = null; // abort scrolling
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this._autoScrollPopup.showPopup(document.documentElement,
|
this._autoScrollPopup.showPopup(document.documentElement,
|
||||||
screenX,
|
event.screenX,
|
||||||
screenY,
|
event.screenY,
|
||||||
"popup", null, null);
|
"popup", null, null);
|
||||||
this._ignoreMouseEvents = true;
|
this._ignoreMouseEvents = true;
|
||||||
this._scrolling = true;
|
this._startX = event.screenX;
|
||||||
this._startX = screenX;
|
this._startY = event.screenY;
|
||||||
this._startY = screenY;
|
this._screenX = event.screenX;
|
||||||
|
this._screenY = event.screenY;
|
||||||
|
this._scrollErrorX = 0;
|
||||||
|
this._scrollErrorY = 0;
|
||||||
|
this._lastFrame = window.mozAnimationStartTime;
|
||||||
|
|
||||||
window.addEventListener("mousemove", this, true);
|
window.addEventListener("mousemove", this, true);
|
||||||
window.addEventListener("mousedown", this, true);
|
window.addEventListener("mousedown", this, true);
|
||||||
|
@ -977,18 +1011,144 @@
|
||||||
window.addEventListener("keydown", this, true);
|
window.addEventListener("keydown", this, true);
|
||||||
window.addEventListener("keypress", this, true);
|
window.addEventListener("keypress", this, true);
|
||||||
window.addEventListener("keyup", this, true);
|
window.addEventListener("keyup", this, true);
|
||||||
]]></body>
|
|
||||||
|
window.mozRequestAnimationFrame(this);
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="_roundToZero">
|
||||||
|
<parameter name="num"/>
|
||||||
|
<body>
|
||||||
|
<![CDATA[
|
||||||
|
if (num > 0)
|
||||||
|
return Math.floor(num);
|
||||||
|
return Math.ceil(num);
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="_accelerate">
|
||||||
|
<parameter name="curr"/>
|
||||||
|
<parameter name="start"/>
|
||||||
|
<body>
|
||||||
|
<![CDATA[
|
||||||
|
const speed = 12;
|
||||||
|
var val = (curr - start) / speed;
|
||||||
|
|
||||||
|
if (val > 1)
|
||||||
|
return val * Math.sqrt(val) - 1;
|
||||||
|
if (val < -1)
|
||||||
|
return val * Math.sqrt(-val) + 1;
|
||||||
|
return 0;
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="autoScrollLoop">
|
||||||
|
<parameter name="timestamp"/>
|
||||||
|
<body>
|
||||||
|
<![CDATA[
|
||||||
|
if (!this._scrollable) {
|
||||||
|
// Scrolling has been canceled
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// avoid long jumps when the browser hangs for more than
|
||||||
|
// |maxTimeDelta| ms
|
||||||
|
const maxTimeDelta = 100;
|
||||||
|
var timeDelta = Math.min(maxTimeDelta, timestamp - this._lastFrame);
|
||||||
|
// we used to scroll |_accelerate()| pixels every 20ms (50fps)
|
||||||
|
var timeCompensation = timeDelta / 20;
|
||||||
|
this._lastFrame = timestamp;
|
||||||
|
|
||||||
|
var actualScrollX = 0;
|
||||||
|
var actualScrollY = 0;
|
||||||
|
// don't bother scrolling vertically when the scrolldir is only horizontal
|
||||||
|
// and the other way around
|
||||||
|
var scrolldir = this._autoScrollPopup.getAttribute("scrolldir");
|
||||||
|
if (scrolldir != 'EW') {
|
||||||
|
var y = this._accelerate(this._screenY, this._startY) * timeCompensation;
|
||||||
|
var desiredScrollY = this._scrollErrorY + y;
|
||||||
|
actualScrollY = this._roundToZero(desiredScrollY);
|
||||||
|
this._scrollErrorY = (desiredScrollY - actualScrollY);
|
||||||
|
}
|
||||||
|
if (scrolldir != 'NS') {
|
||||||
|
var x = this._accelerate(this._screenX, this._startX) * timeCompensation;
|
||||||
|
var desiredScrollX = this._scrollErrorX + x;
|
||||||
|
actualScrollX = this._roundToZero(desiredScrollX);
|
||||||
|
this._scrollErrorX = (desiredScrollX - actualScrollX);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._scrollable instanceof Window)
|
||||||
|
this._scrollable.scrollBy(actualScrollX, actualScrollY);
|
||||||
|
else { // an element with overflow
|
||||||
|
this._scrollable.scrollLeft += actualScrollX;
|
||||||
|
this._scrollable.scrollTop += actualScrollY;
|
||||||
|
}
|
||||||
|
window.mozRequestAnimationFrame(this);
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
|
<method name="isAutoscrollBlocker">
|
||||||
|
<parameter name="node"/>
|
||||||
|
<body>
|
||||||
|
<![CDATA[
|
||||||
|
var mmPaste = false;
|
||||||
|
var mmScrollbarPosition = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
mmPaste = this.mPrefs.getBoolPref("middlemouse.paste");
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mmScrollbarPosition = this.mPrefs.getBoolPref("middlemouse.scrollbarPosition");
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
while (node) {
|
||||||
|
if ((node instanceof HTMLAnchorElement || node instanceof HTMLAreaElement) && node.hasAttribute("href"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (mmPaste && (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (node instanceof XULElement && mmScrollbarPosition
|
||||||
|
&& (node.localName == "scrollbar" || node.localName == "scrollcorner"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
node = node.parentNode;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<!-- nsIFrameRequestCallback implementation -->
|
||||||
|
<method name="sample">
|
||||||
|
<parameter name="timeStamp"/>
|
||||||
|
<body>
|
||||||
|
<![CDATA[
|
||||||
|
this.autoScrollLoop(timeStamp);
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<method name="handleEvent">
|
<method name="handleEvent">
|
||||||
<parameter name="aEvent"/>
|
<parameter name="aEvent"/>
|
||||||
<body>
|
<body>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
if (this._scrolling) {
|
if (this._scrollable) {
|
||||||
switch(aEvent.type) {
|
switch(aEvent.type) {
|
||||||
case "mousemove": {
|
case "mousemove": {
|
||||||
var x = aEvent.screenX - this._startX;
|
this._screenX = aEvent.screenX;
|
||||||
var y = aEvent.screenY - this._startY;
|
this._screenY = aEvent.screenY;
|
||||||
|
|
||||||
|
var x = this._screenX - this._startX;
|
||||||
|
var y = this._screenY - this._startY;
|
||||||
|
|
||||||
if ((x > this._AUTOSCROLL_SNAP || x < -this._AUTOSCROLL_SNAP) ||
|
if ((x > this._AUTOSCROLL_SNAP || x < -this._AUTOSCROLL_SNAP) ||
|
||||||
(y > this._AUTOSCROLL_SNAP || y < -this._AUTOSCROLL_SNAP))
|
(y > this._AUTOSCROLL_SNAP || y < -this._AUTOSCROLL_SNAP))
|
||||||
|
@ -1155,6 +1315,17 @@
|
||||||
}
|
}
|
||||||
]]>
|
]]>
|
||||||
</handler>
|
</handler>
|
||||||
|
<handler event="mousedown" phase="capturing">
|
||||||
|
<![CDATA[
|
||||||
|
if (!this._scrollable && event.button == 1) {
|
||||||
|
if (!this.autoscrollEnabled ||
|
||||||
|
this.isAutoscrollBlocker(event.originalTarget))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.startScroll(event);
|
||||||
|
}
|
||||||
|
]]>
|
||||||
|
</handler>
|
||||||
<handler event="dragover" group="system">
|
<handler event="dragover" group="system">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
if (!this.droppedLinkHandler || event.defaultPrevented)
|
if (!this.droppedLinkHandler || event.defaultPrevented)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
<binding id="remote-browser" extends="chrome://global/content/bindings/browser.xml#browser">
|
<binding id="remote-browser" extends="chrome://global/content/bindings/browser.xml#browser">
|
||||||
|
|
||||||
<implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIMessageListener">
|
<implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIMessageListener, nsIMessageListener">
|
||||||
|
|
||||||
<field name="_securityUI">null</field>
|
<field name="_securityUI">null</field>
|
||||||
|
|
||||||
|
@ -265,13 +265,7 @@
|
||||||
Cu.import("resource://gre/modules/SelectParentHelper.jsm");
|
Cu.import("resource://gre/modules/SelectParentHelper.jsm");
|
||||||
let dropdown = document.getElementById(this.getAttribute("selectpopup"));
|
let dropdown = document.getElementById(this.getAttribute("selectpopup"));
|
||||||
SelectParentHelper.hide(dropdown);
|
SelectParentHelper.hide(dropdown);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
// Delegate to browser.xml.
|
|
||||||
return this._receiveMessage(aMessage);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче