mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Improve kinetic panning and add constants to customise behaviour.
Increase the number of considered motion events and add some constants to control the kinetic panning behaviour. This should make it a lot less glitchy.
This commit is contained in:
parent
162b480291
commit
c3ab0aab11
@ -7,6 +7,24 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm")
|
||||
|
||||
// The ratio of velocity that is retained every ms.
|
||||
const kPanDeceleration = 0.999;
|
||||
|
||||
// The number of ms to consider events over for a swipe gesture.
|
||||
const kSwipeLength = 1000;
|
||||
|
||||
// Minimum speed to move during kinetic panning. 0.015 pixels/ms is roughly
|
||||
// equivalent to a pixel every 4 frames at 60fps.
|
||||
const kMinKineticSpeed = 0.015;
|
||||
|
||||
// Maximum kinetic panning speed. 3 pixels/ms is equivalent to 50 pixels per
|
||||
// frame at 60fps.
|
||||
const kMaxKineticSpeed = 3;
|
||||
|
||||
// The maximum magnitude of disparity allowed between axes acceleration. If
|
||||
// it's larger than this, lock the slow-moving axis.
|
||||
const kAxisLockRatio = 5;
|
||||
|
||||
function dump(a) {
|
||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(a);
|
||||
}
|
||||
@ -319,9 +337,6 @@ Tab.prototype = {
|
||||
|
||||
var BrowserEventHandler = {
|
||||
init: function init() {
|
||||
this.motionBuffer = [];
|
||||
this._updateLastPosition(0, 0, 0, 0);
|
||||
|
||||
window.addEventListener("click", this, true);
|
||||
window.addEventListener("mousedown", this, true);
|
||||
window.addEventListener("mouseup", this, true);
|
||||
@ -407,13 +422,11 @@ var BrowserEventHandler = {
|
||||
this.firstXMovement = 0;
|
||||
this.firstYMovement = 0;
|
||||
|
||||
this.motionBuffer = [];
|
||||
this._updateLastPosition(aEvent.clientX, aEvent.clientY, 0, 0);
|
||||
this.panElement = this._findScrollableElement(aEvent.originalTarget,
|
||||
true);
|
||||
|
||||
// Set panning to true *after* calling updateLastPosition, so
|
||||
// that it can clear the motion buffer the first time we call
|
||||
// it.
|
||||
if (this.panElement)
|
||||
this.panning = true;
|
||||
|
||||
@ -486,19 +499,18 @@ var BrowserEventHandler = {
|
||||
this.blockClick = true;
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
|
||||
if (isDrag &&
|
||||
(this.motionBuffer[4].time - this.motionBuffer[0].time) < 1000) {
|
||||
// We've exceeded the scroll threshold, start kinetic pan
|
||||
|
||||
// Find the average velocity over the last few motion events
|
||||
this.panLastTime = window.mozAnimationStartTime;
|
||||
this.panX = 0;
|
||||
this.panY = 0;
|
||||
let nEvents = 0;
|
||||
for (let i = 1; i < 5; i++) {
|
||||
for (let i = 0; i < this.motionBuffer.length - 1; i++) {
|
||||
if (this.motionBuffer[i].time < this.panLastTime - kSwipeLength)
|
||||
break;
|
||||
|
||||
let timeDelta = this.motionBuffer[i].time -
|
||||
this.motionBuffer[i - 1].time;
|
||||
this.motionBuffer[i + 1].time;
|
||||
if (timeDelta <= 0)
|
||||
continue;
|
||||
|
||||
@ -506,11 +518,19 @@ var BrowserEventHandler = {
|
||||
this.panY += this.motionBuffer[i].dy / timeDelta;
|
||||
nEvents ++;
|
||||
}
|
||||
if (nEvents == 0)
|
||||
break;
|
||||
|
||||
this.panX /= nEvents;
|
||||
this.panY /= nEvents;
|
||||
if (Math.abs(this.panX) > kMaxKineticSpeed)
|
||||
this.panX = (this.panX > 0) ? kMaxKineticSpeed : -kMaxKineticSpeed;
|
||||
if (Math.abs(this.panY) > kMaxKineticSpeed)
|
||||
this.panY = (this.panY > 0) ? kMaxKineticSpeed : -kMaxKineticSpeed;
|
||||
|
||||
// If we have zero acceleration, bail out.
|
||||
if (this.panX == 0 && this.panY == 0)
|
||||
// If we have (near) zero acceleration, bail out.
|
||||
if (Math.abs(this.panX) < kMinKineticSpeed &&
|
||||
Math.abs(this.panY) < kMinKineticSpeed)
|
||||
break;
|
||||
|
||||
// Check if this element can scroll - if not, let's bail out.
|
||||
@ -522,10 +542,8 @@ var BrowserEventHandler = {
|
||||
this._scrollElementBy(this.panElement, -this.panX, -this.panY);
|
||||
|
||||
// TODO: Use the kinetic scrolling prefs
|
||||
this.panDeceleration = 0.999;
|
||||
this.panAccumulatedDeltaX = 0;
|
||||
this.panAccumulatedDeltaY = 0;
|
||||
this.panLastTime = window.mozAnimationStartTime;
|
||||
|
||||
let self = this;
|
||||
let panElement = this.panElement;
|
||||
@ -538,8 +556,8 @@ var BrowserEventHandler = {
|
||||
self.panLastTime = timeStamp;
|
||||
|
||||
// Adjust deceleration
|
||||
self.panX *= Math.pow(self.panDeceleration, timeDelta);
|
||||
self.panY *= Math.pow(self.panDeceleration, timeDelta);
|
||||
self.panX *= Math.pow(kPanDeceleration, timeDelta);
|
||||
self.panY *= Math.pow(kPanDeceleration, timeDelta);
|
||||
|
||||
// Calculate panning motion
|
||||
let dx = self.panX * timeDelta;
|
||||
@ -566,20 +584,16 @@ var BrowserEventHandler = {
|
||||
|
||||
self._scrollElementBy(panElement, -dx, -dy);
|
||||
|
||||
// If we're moving at a rate slower than 0.015
|
||||
// pixels/ms, stop requesting frames.
|
||||
// This is roughly equivalent to a pixel every
|
||||
// 4 frames at 60fps.
|
||||
if (Math.abs(self.panX) >= 0.015 || Math.abs(self.panY) >= 0.015)
|
||||
if (Math.abs(self.panX) >= kMinKineticSpeed ||
|
||||
Math.abs(self.panY) >= kMinKineticSpeed)
|
||||
window.mozRequestAnimationFrame(this);
|
||||
}
|
||||
};
|
||||
|
||||
// If one axis is moving more than five times faster than
|
||||
// the other, lock to that axis.
|
||||
if (Math.abs(this.panX) < Math.abs(this.panY) / 5)
|
||||
// If one axis is moving a lot slower than the other, lock it.
|
||||
if (Math.abs(this.panX) < Math.abs(this.panY) / kAxisLockRatio)
|
||||
this.panX = 0;
|
||||
else if (Math.abs(this.panY) < Math.abs(this.panX) / 5)
|
||||
else if (Math.abs(this.panY) < Math.abs(this.panX) / kAxisLockRatio)
|
||||
this.panY = 0;
|
||||
|
||||
// Start the panning animation
|
||||
@ -611,16 +625,7 @@ var BrowserEventHandler = {
|
||||
this.lastY = y;
|
||||
this.lastTime = Date.now();
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (this.panning) {
|
||||
this.motionBuffer[i] = this.motionBuffer[i + 1];
|
||||
} else {
|
||||
this.motionBuffer[i] = { dx: 0, dy: 0, time: this.lastTime };
|
||||
}
|
||||
}
|
||||
|
||||
this.motionBuffer[4] =
|
||||
{ dx: dx, dy: dy, time: this.lastTime };
|
||||
this.motionBuffer.unshift({ dx: dx, dy: dy, time: this.lastTime });
|
||||
},
|
||||
|
||||
_findScrollableElement: function(elem, checkElem) {
|
||||
|
Loading…
Reference in New Issue
Block a user