зеркало из https://github.com/mozilla/gecko-dev.git
Bug 938359 - [e10s] Support middle-click scroll (r=felipe)
This commit is contained in:
Родитель
8cbfbdc3ad
Коммит
482b2b1730
|
@ -8,6 +8,7 @@ let Ci = Components.interfaces;
|
|||
let Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ContentLinkHandler",
|
||||
"resource:///modules/ContentLinkHandler.jsm");
|
||||
|
|
|
@ -68,10 +68,6 @@
|
|||
|
||||
<field name="contentWindowId">null</field>
|
||||
|
||||
<property name="messageManager"
|
||||
onget="return this._frameLoader.messageManager;"
|
||||
readonly="true"/>
|
||||
|
||||
<field name="_contentTitle">null</field>
|
||||
|
||||
<field name="_ios">
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
/* -*- 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,6 +28,7 @@ toolkit.jar:
|
|||
content/global/plugins.html
|
||||
content/global/plugins.css
|
||||
content/global/browser-child.js (browser-child.js)
|
||||
content/global/browser-content.js (browser-content.js)
|
||||
*+ content/global/buildconfig.html (buildconfig.html)
|
||||
+ content/global/charsetOverlay.js (charsetOverlay.js)
|
||||
+ content/global/charsetOverlay.xul (charsetOverlay.xul)
|
||||
|
|
|
@ -75,7 +75,10 @@ function test()
|
|||
ok((scrollHori && elem.scrollLeft > 0) ||
|
||||
(!scrollHori && elem.scrollLeft == 0),
|
||||
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 },
|
||||
gBrowser.contentWindow);
|
||||
|
|
|
@ -90,6 +90,12 @@ function test()
|
|||
EventUtils.synthesizeMouse(root, 10, 10, { button: 1 },
|
||||
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.
|
||||
expectedKeyEvents = kNoKeyEvents;
|
||||
sendChar("A");
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<content clickthrough="never">
|
||||
<children/>
|
||||
</content>
|
||||
<implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIFrameRequestCallback">
|
||||
<implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIFrameRequestCallback, nsIMessageListener">
|
||||
<property name="autoscrollEnabled">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
|
@ -600,14 +600,6 @@
|
|||
if (!tabBrowser || !("fastFind" in tabBrowser) ||
|
||||
tabBrowser.selectedBrowser == this)
|
||||
this.fastFind.setDocShell(this.docShell);
|
||||
|
||||
if (this._scrollable) {
|
||||
var doc =
|
||||
this._scrollable.ownerDocument || this._scrollable.document;
|
||||
if (doc == aEvent.target) {
|
||||
this._autoScrollPopup.hidePopup();
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -793,6 +785,12 @@
|
|||
this.addEventListener("pageshow", this.onPageShow, true);
|
||||
this.addEventListener("pagehide", this.onPageHide, 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>
|
||||
|
||||
|
@ -843,6 +841,34 @@
|
|||
</body>
|
||||
</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">
|
||||
<parameter name="aSubject"/>
|
||||
<parameter name="aTopic"/>
|
||||
|
@ -871,20 +897,17 @@
|
|||
</method>
|
||||
|
||||
<field name="_AUTOSCROLL_SNAP">10</field>
|
||||
<field name="_scrollable">null</field>
|
||||
<field name="_scrolling">false</field>
|
||||
<field name="_startX">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="_autoScrollNeedsCleanup">false</field>
|
||||
|
||||
<method name="stopScroll">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._scrollable) {
|
||||
this._scrollable = null;
|
||||
if (this._scrolling) {
|
||||
this._scrolling = false;
|
||||
window.removeEventListener("mousemove", this, true);
|
||||
window.removeEventListener("mousedown", this, true);
|
||||
window.removeEventListener("mouseup", this, true);
|
||||
|
@ -892,6 +915,7 @@
|
|||
window.removeEventListener("keydown", this, true);
|
||||
window.removeEventListener("keypress", this, true);
|
||||
window.removeEventListener("keyup", this, true);
|
||||
this.messageManager.sendAsyncMessage("Autoscroll:Stop");
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
|
@ -909,9 +933,10 @@
|
|||
</method>
|
||||
|
||||
<method name="startScroll">
|
||||
<parameter name="event"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
<parameter name="scrolldir"/>
|
||||
<parameter name="screenX"/>
|
||||
<parameter name="screenY"/>
|
||||
<body><![CDATA[
|
||||
if (!this._autoScrollPopup) {
|
||||
if (this.hasAttribute("autoscrollpopup")) {
|
||||
// our creator provided a popup to share
|
||||
|
@ -933,75 +958,16 @@
|
|||
this._autoScrollPopup.setAttribute("translucent", /Win|Mac/.test(navigator.platform));
|
||||
}
|
||||
|
||||
// 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.setAttribute("scrolldir", scrolldir);
|
||||
this._autoScrollPopup.addEventListener("popuphidden", this, true);
|
||||
this._autoScrollPopup.showPopup(document.documentElement,
|
||||
event.screenX,
|
||||
event.screenY,
|
||||
screenX,
|
||||
screenY,
|
||||
"popup", null, null);
|
||||
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 = window.mozAnimationStartTime;
|
||||
this._scrolling = true;
|
||||
this._startX = screenX;
|
||||
this._startY = screenY;
|
||||
|
||||
window.addEventListener("mousemove", this, true);
|
||||
window.addEventListener("mousedown", this, true);
|
||||
|
@ -1010,144 +976,19 @@
|
|||
window.addEventListener("keydown", this, true);
|
||||
window.addEventListener("keypress", this, true);
|
||||
window.addEventListener("keyup", this, true);
|
||||
|
||||
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 name="handleEvent">
|
||||
<parameter name="aEvent"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this._scrollable) {
|
||||
if (this._scrolling) {
|
||||
switch(aEvent.type) {
|
||||
case "mousemove": {
|
||||
this._screenX = aEvent.screenX;
|
||||
this._screenY = aEvent.screenY;
|
||||
|
||||
var x = this._screenX - this._startX;
|
||||
var y = this._screenY - this._startY;
|
||||
var x = aEvent.screenX - this._startX;
|
||||
var y = aEvent.screenY - this._startY;
|
||||
|
||||
if ((x > this._AUTOSCROLL_SNAP || x < -this._AUTOSCROLL_SNAP) ||
|
||||
(y > this._AUTOSCROLL_SNAP || y < -this._AUTOSCROLL_SNAP))
|
||||
|
@ -1314,17 +1155,6 @@
|
|||
}
|
||||
]]>
|
||||
</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">
|
||||
<![CDATA[
|
||||
if (!this.droppedLinkHandler || event.defaultPrevented)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<binding id="remote-browser" extends="chrome://global/content/bindings/browser.xml#browser">
|
||||
|
||||
<implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIMessageListener, nsIMessageListener">
|
||||
<implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIMessageListener">
|
||||
|
||||
<field name="_securityUI">null</field>
|
||||
|
||||
|
@ -265,7 +265,13 @@
|
|||
Cu.import("resource://gre/modules/SelectParentHelper.jsm");
|
||||
let dropdown = document.getElementById(this.getAttribute("selectpopup"));
|
||||
SelectParentHelper.hide(dropdown);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Delegate to browser.xml.
|
||||
return this._receiveMessage(aMessage);
|
||||
break;
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
|
Загрузка…
Ссылка в новой задаче