Bug 1516266 - Part 2 - Unify the "arrowscrollbox" and "arrowscrollbox-clicktoscroll" bindings. r=bgrins

Differential Revision: https://phabricator.services.mozilla.com/D15302

--HG--
extra : rebase_source : 59943ee24426d39375b1d0eb7f0fc454ba6f00ab
This commit is contained in:
Paolo Amadini 2018-12-26 14:49:14 +00:00
Родитель 357da38a59
Коммит 5dca426062
3 изменённых файлов: 168 добавлений и 216 удалений

Просмотреть файл

@ -9,7 +9,7 @@
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="tabbrowser-arrowscrollbox" extends="chrome://global/content/bindings/scrollbox.xml#arrowscrollbox-clicktoscroll">
<binding id="tabbrowser-arrowscrollbox" extends="chrome://global/content/bindings/scrollbox.xml#arrowscrollbox">
<implementation>
<!-- Override scrollbox.xml method, since our scrollbox's children are
inherited from the binding parent -->

Просмотреть файл

@ -76,6 +76,49 @@
document.getAnonymousElementByAttribute(this, "anonid", "scrollbutton-down");
</field>
<field name="_scrollIndex">0</field>
<field name="_arrowScrollAnim"><![CDATA[({
scrollbox: this,
requestHandle: 0, /* 0 indicates there is no pending request */
start: function arrowSmoothScroll_start() {
this.lastFrameTime = window.performance.now();
if (!this.requestHandle)
this.requestHandle = window.requestAnimationFrame(this.sample.bind(this));
},
stop: function arrowSmoothScroll_stop() {
window.cancelAnimationFrame(this.requestHandle);
this.requestHandle = 0;
},
sample: function arrowSmoothScroll_handleEvent(timeStamp) {
const scrollIndex = this.scrollbox._scrollIndex;
const timePassed = timeStamp - this.lastFrameTime;
this.lastFrameTime = timeStamp;
const scrollDelta = 0.5 * timePassed * scrollIndex;
this.scrollbox.scrollByPixels(scrollDelta, true);
this.requestHandle = window.requestAnimationFrame(this.sample.bind(this));
},
})]]></field>
<property name="_clickToScroll" readonly="true">
<getter><![CDATA[
return this.hasAttribute("clicktoscroll");
]]></getter>
</property>
<property name="_scrollDelay" readonly="true">
<getter><![CDATA[
if (this._clickToScroll) {
return this._prefBranch.getIntPref(
"toolkit.scrollbox.clickToScroll.scrollDelay", 150);
}
// Use the same REPEAT_DELAY as "nsRepeatService.h".
return /Mac/.test(navigator.platform) ? 25 : 50;
]]></getter>
</property>
<field name="__prefBranch">null</field>
<property name="_prefBranch" readonly="true">
<getter><![CDATA[
@ -167,6 +210,9 @@
<method name="_onButtonClick">
<parameter name="event"/>
<body><![CDATA[
if (this._clickToScroll) {
this._distanceScroll(event);
}
]]></body>
</method>
@ -174,26 +220,40 @@
<parameter name="event"/>
<parameter name="index"/>
<body><![CDATA[
if (this._clickToScroll && event.button == 0) {
this._startScroll(index);
}
]]></body>
</method>
<method name="_onButtonMouseUp">
<parameter name="event"/>
<body><![CDATA[
if (this._clickToScroll && event.button == 0) {
this._stopScroll();
}
]]></body>
</method>
<method name="_onButtonMouseOver">
<parameter name="index"/>
<body><![CDATA[
this._startScroll(index);
if (this._clickToScroll) {
this._continueScroll(index);
} else {
this._startScroll(index);
}
]]></body>
</method>
<method name="_onButtonMouseOut">
<parameter name="index"/>
<body><![CDATA[
this._stopScroll();
if (this._clickToScroll) {
this._pauseScroll();
} else {
this._stopScroll();
}
]]></body>
</method>
@ -347,19 +407,37 @@
index *= -1;
}
if (this._clickToScroll) {
this._scrollIndex = index;
this._mousedown = true;
if (this.smoothScroll) {
this._arrowScrollAnim.start();
return;
}
}
if (!this._scrollTimer) {
this._scrollTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
} else {
this._scrollTimer.cancel();
}
let callback = () => this.scrollByPixels(this.scrollIncrement * index);
let callback;
if (this._clickToScroll) {
callback = () => {
if (!document && this._scrollTimer) {
this._scrollTimer.cancel();
}
this.scrollByIndex(this._scrollIndex);
};
} else {
callback = () => this.scrollByPixels(this.scrollIncrement * index);
}
// Use the same REPEAT_DELAY as "nsRepeatService.h".
let scrollDelay = /Mac/.test(navigator.platform) ? 25 : 50;
this._scrollTimer.initWithCallback(callback, scrollDelay,
this._scrollTimer.initWithCallback(callback, this._scrollDelay,
Ci.nsITimer.TYPE_REPEATING_SLACK);
callback();
]]>
</body>
@ -369,6 +447,88 @@
<body><![CDATA[
if (this._scrollTimer)
this._scrollTimer.cancel();
if (this._clickToScroll) {
this._mousedown = false;
if (!this._scrollIndex || !this.smoothScroll)
return;
this.scrollByIndex(this._scrollIndex);
this._scrollIndex = 0;
this._arrowScrollAnim.stop();
}
]]></body>
</method>
<method name="_pauseScroll">
<body><![CDATA[
if (this._mousedown) {
this._stopScroll();
this._mousedown = true;
document.addEventListener("mouseup", this);
document.addEventListener("blur", this, true);
}
]]></body>
</method>
<method name="_continueScroll">
<parameter name="index"/>
<body><![CDATA[
if (this._mousedown)
this._startScroll(index);
]]></body>
</method>
<method name="_distanceScroll">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.detail < 2 || aEvent.detail > 3)
return;
var scrollBack = (aEvent.originalTarget == this._scrollButtonUp);
var scrollLeftOrUp = this._isRTLScrollbox ? !scrollBack : scrollBack;
var targetElement;
if (aEvent.detail == 2) {
// scroll by the size of the scrollbox
let [start, end] = this._startEndProps;
let x;
if (scrollLeftOrUp)
x = this.scrollClientRect[start] - this.scrollClientSize;
else
x = this.scrollClientRect[end] + this.scrollClientSize;
targetElement = this._elementFromPoint(x, scrollLeftOrUp ? -1 : 1);
// the next partly-hidden element will become fully visible,
// so don't scroll too far
if (targetElement)
targetElement = scrollBack ?
targetElement.nextElementSibling :
targetElement.previousElementSibling;
}
if (!targetElement) {
// scroll to the first resp. last element
let elements = this._getScrollableElements();
targetElement = scrollBack ?
elements[0] :
elements[elements.length - 1];
}
this.ensureElementIsVisible(targetElement);
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.type == "mouseup" ||
aEvent.type == "blur" && aEvent.target == document) {
this._mousedown = false;
document.removeEventListener("mouseup", this);
document.removeEventListener("blur", this, true);
}
]]></body>
</method>
@ -618,208 +778,4 @@
]]></handler>
</handlers>
</binding>
<binding id="arrowscrollbox-clicktoscroll" extends="chrome://global/content/bindings/scrollbox.xml#arrowscrollbox">
<implementation>
<constructor><![CDATA[
this._scrollDelay =
this._prefBranch.getIntPref("toolkit.scrollbox.clickToScroll.scrollDelay",
this._scrollDelay);
]]></constructor>
<destructor><![CDATA[
// Release timer to avoid reference cycles.
if (this._scrollTimer) {
this._scrollTimer.cancel();
this._scrollTimer = null;
}
]]></destructor>
<field name="_scrollIndex">0</field>
<field name="_scrollDelay">150</field>
<field name="_arrowScrollAnim"><![CDATA[({
scrollbox: this,
requestHandle: 0, /* 0 indicates there is no pending request */
start: function arrowSmoothScroll_start() {
this.lastFrameTime = window.performance.now();
if (!this.requestHandle)
this.requestHandle = window.requestAnimationFrame(this.sample.bind(this));
},
stop: function arrowSmoothScroll_stop() {
window.cancelAnimationFrame(this.requestHandle);
this.requestHandle = 0;
},
sample: function arrowSmoothScroll_handleEvent(timeStamp) {
const scrollIndex = this.scrollbox._scrollIndex;
const timePassed = timeStamp - this.lastFrameTime;
this.lastFrameTime = timeStamp;
const scrollDelta = 0.5 * timePassed * scrollIndex;
this.scrollbox.scrollByPixels(scrollDelta, true);
this.requestHandle = window.requestAnimationFrame(this.sample.bind(this));
},
})]]></field>
<method name="_onButtonClick">
<parameter name="event"/>
<body><![CDATA[
this._distanceScroll(event);
]]></body>
</method>
<method name="_onButtonMouseDown">
<parameter name="event"/>
<parameter name="index"/>
<body><![CDATA[
if (event.button == 0) {
this._startScroll(index);
}
]]></body>
</method>
<method name="_onButtonMouseUp">
<parameter name="event"/>
<body><![CDATA[
if (event.button == 0) {
this._stopScroll();
}
]]></body>
</method>
<method name="_onButtonMouseOver">
<parameter name="index"/>
<body><![CDATA[
this._continueScroll(index);
]]></body>
</method>
<method name="_onButtonMouseOut">
<body><![CDATA[
this._pauseScroll();
]]></body>
</method>
<method name="_startScroll">
<parameter name="index"/>
<body><![CDATA[
if (this._isRTLScrollbox)
index *= -1;
this._scrollIndex = index;
this._mousedown = true;
if (this.smoothScroll) {
this._arrowScrollAnim.start();
return;
}
if (!this._scrollTimer)
this._scrollTimer =
Cc["@mozilla.org/timer;1"]
.createInstance(Ci.nsITimer);
else
this._scrollTimer.cancel();
let callback = () => {
if (!document && this._scrollTimer) {
this._scrollTimer.cancel();
}
this.scrollByIndex(this._scrollIndex);
};
this._scrollTimer.initWithCallback(callback, this._scrollDelay,
this._scrollTimer.TYPE_REPEATING_SLACK);
callback();
]]>
</body>
</method>
<method name="_stopScroll">
<body><![CDATA[
if (this._scrollTimer)
this._scrollTimer.cancel();
this._mousedown = false;
if (!this._scrollIndex || !this.smoothScroll)
return;
this.scrollByIndex(this._scrollIndex);
this._scrollIndex = 0;
this._arrowScrollAnim.stop();
]]></body>
</method>
<method name="_pauseScroll">
<body><![CDATA[
if (this._mousedown) {
this._stopScroll();
this._mousedown = true;
document.addEventListener("mouseup", this);
document.addEventListener("blur", this, true);
}
]]></body>
</method>
<method name="_continueScroll">
<parameter name="index"/>
<body><![CDATA[
if (this._mousedown)
this._startScroll(index);
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.type == "mouseup" ||
aEvent.type == "blur" && aEvent.target == document) {
this._mousedown = false;
document.removeEventListener("mouseup", this);
document.removeEventListener("blur", this, true);
}
]]></body>
</method>
<method name="_distanceScroll">
<parameter name="aEvent"/>
<body><![CDATA[
if (aEvent.detail < 2 || aEvent.detail > 3)
return;
var scrollBack = (aEvent.originalTarget == this._scrollButtonUp);
var scrollLeftOrUp = this._isRTLScrollbox ? !scrollBack : scrollBack;
var targetElement;
if (aEvent.detail == 2) {
// scroll by the size of the scrollbox
let [start, end] = this._startEndProps;
let x;
if (scrollLeftOrUp)
x = this.scrollClientRect[start] - this.scrollClientSize;
else
x = this.scrollClientRect[end] + this.scrollClientSize;
targetElement = this._elementFromPoint(x, scrollLeftOrUp ? -1 : 1);
// the next partly-hidden element will become fully visible,
// so don't scroll too far
if (targetElement)
targetElement = scrollBack ?
targetElement.nextElementSibling :
targetElement.previousElementSibling;
}
if (!targetElement) {
// scroll to the first resp. last element
let elements = this._getScrollableElements();
targetElement = scrollBack ?
elements[0] :
elements[elements.length - 1];
}
this.ensureElementIsVisible(targetElement);
]]></body>
</method>
</implementation>
</binding>
</bindings>

Просмотреть файл

@ -678,10 +678,6 @@ arrowscrollbox {
-moz-binding: url("chrome://global/content/bindings/scrollbox.xml#arrowscrollbox");
}
arrowscrollbox[clicktoscroll="true"] {
-moz-binding: url("chrome://global/content/bindings/scrollbox.xml#arrowscrollbox-clicktoscroll");
}
/********** stringbundle **********/
stringbundle,