Use mozRequestAnimationFrame to animate autoscroll; r=neil@parkwaycc.co.uk a=bsmedberg

This commit is contained in:
Arpad Borsos 2010-08-18 19:57:31 +02:00
parent 1459c6c313
commit e9340d208f
2 changed files with 49 additions and 20 deletions

View File

@ -29,14 +29,13 @@ function test()
}
var elem = doc.getElementById(test.elem);
EventUtils.synthesizeMouse(elem, 50, 50, { button: 1 },
gBrowser.contentWindow);
EventUtils.synthesizeMouse(elem, 100, 100,
{ type: "mousemove", clickCount: "0" },
gBrowser.contentWindow);
// the autoscroll implementation uses a 20ms interval
// wait for 40ms to make sure it did autoscroll at least once
setTimeout(function () {
// skip a few frames before checking the tests
var skipFrames = 3;
var checkScroll = function () {
if (skipFrames--) {
window.mozRequestAnimationFrame();
return;
}
EventUtils.synthesizeKey("VK_ESCAPE", {}, gBrowser.contentWindow);
var scrollVert = test.expected & expectScrollVert;
ok((scrollVert && elem.scrollTop > 0) ||
@ -46,12 +45,26 @@ function test()
ok((scrollHori && elem.scrollLeft > 0) ||
(!scrollHori && elem.scrollLeft == 0),
test.elem+' should'+(scrollHori ? '' : ' not')+' have scrolled horizontally');
window.removeEventListener("MozAfterPaint", checkScroll, false);
nextTest();
}, 40);
};
EventUtils.synthesizeMouse(elem, 50, 50, { button: 1 },
gBrowser.contentWindow);
EventUtils.synthesizeMouse(elem, 100, 100,
{ type: "mousemove", clickCount: "0" },
gBrowser.contentWindow);
window.addEventListener("MozAfterPaint", checkScroll, false);
/*
* if scrolling didnt work, we wouldnt do any redraws and thus time out.
* so request and force redraws to get the chance to check for scrolling at
* all.
*/
window.mozRequestAnimationFrame();
}
waitForExplicitFinish();
var dataUri = 'data:text/html,<body><style type="text/css">div { display: inline-block; }</style>\
<div id="forceredraw" style="height: 1px"></div>\
<div id="a" style="width: 100px; height: 100px; overflow: hidden;"><div style="width: 200px; height: 200px;"></div></div>\
<div id="b" style="width: 100px; height: 100px; overflow: auto;"><div style="width: 200px; height: 200px;"></div></div>\
<div id="c" style="width: 100px; height: 100px; overflow-x: auto; overflow-y: hidden;"><div style="width: 200px; height: 200px;"></div></div>\
@ -75,6 +88,10 @@ function test()
function onFocus() {
doc = gBrowser.contentDocument;
// force redraws, so we actually get AfterPaint events
window.addEventListener("MozBeforePaint", function(ev) {
doc.getElementById("forceredraw").style.left = ev.timeStamp % 100;
}, false);
nextTest();
}

View File

@ -739,15 +739,14 @@
]]>
</body>
</method>
<field name="_AUTOSCROLL_SPEED">3</field>
<field name="_AUTOSCROLL_SNAP">10</field>
<field name="_scrollable">null</field>
<field name="_autoScrollTimer">null</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>
@ -763,7 +762,7 @@
window.removeEventListener("keydown", this, true);
window.removeEventListener("keypress", this, true);
window.removeEventListener("keyup", this, true);
clearInterval(this._autoScrollTimer);
window.removeEventListener("MozBeforePaint", this, true);
}
]]>
</body>
@ -876,6 +875,9 @@
this._startY = event.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("mousedown", this, true);
@ -884,12 +886,9 @@
window.addEventListener("keydown", this, true);
window.addEventListener("keypress", this, true);
window.addEventListener("keyup", this, true);
window.addEventListener("MozBeforePaint", this, true);
this._scrollErrorX = 0;
this._scrollErrorY = 0;
this._autoScrollTimer = setInterval(function(self) { self.autoScrollLoop(); },
20, this);
window.mozRequestAnimationFrame();
]]>
</body>
</method>
@ -923,21 +922,30 @@
</method>
<method name="autoScrollLoop">
<parameter name="timestamp"/>
<body>
<![CDATA[
// 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
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);
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);
var x = this._accelerate(this._screenX, this._startX) * timeCompensation;
var desiredScrollX = this._scrollErrorX + x;
actualScrollX = this._roundToZero(desiredScrollX);
this._scrollErrorX = (desiredScrollX - actualScrollX);
@ -949,6 +957,7 @@
this._scrollable.scrollLeft += actualScrollX;
this._scrollable.scrollTop += actualScrollY;
}
window.mozRequestAnimationFrame();
]]>
</body>
</method>
@ -995,6 +1004,9 @@
<![CDATA[
if (this._scrollable) {
switch(aEvent.type) {
case "MozBeforePaint":
this.autoScrollLoop(aEvent.timeStamp);
break;
case "mousemove": {
this._screenX = aEvent.screenX;
this._screenY = aEvent.screenY;