Fix in-tab close button behavior

Fixes #775 (non-responsiveness when closing multiple tabs by rapidly clicking in-tab close buttons).
This commit is contained in:
MaxKoll 2018-10-08 14:29:20 +02:00 committed by Roy Tam
commit c7545b7d4e

View file

@ -4296,17 +4296,76 @@
event.originalTarget.localName != "box")
return;
// See hack note in the tabbrowser-close-tab-button binding
// See comments in the "mousedown" and "click" event handlers of the
// tabbrowser-tabs binding.
if (!this._blockDblClick)
BrowserOpenTab();
event.preventDefault();
]]></handler>
<handler event="click"><![CDATA[
if (event.button != 1)
return;
<!-- Consider that the in-tab close button is only shown on the active
tab. When clicking on an inactive tab at the position where the
close button will appear during the click, no "click" event will be
dispatched, because the mousedown and mouseup events don't have the
same event target. For that reason use "mousedown" instead of "click"
to implement in-tab close button behavior. (Pale Moon UXP issue #775)
-->
<handler event="mousedown" button="0" phase="capturing"><![CDATA[
/* The only sequence in which a second click event (i.e. dblclik)
* can be dispatched on an in-tab close button is when it is shown
* after the first click (i.e. the first click event was dispatched
* on the tab). This happens when we show the close button only on
* the active tab. (bug 352021)
* The only sequence in which a third click event can be dispatched
* on an in-tab close button is when the tab was opened with a
* double click on the tabbar. (bug 378344)
* In both cases, it is most likely that the close button area has
* been accidentally clicked, therefore we do not close the tab.
*
* We don't want to ignore processing of more than one click event,
* though, since the user might actually be repeatedly clicking to
* close many tabs at once.
*
* Also prevent errant doubleclick on the close button from opening
* a new tab (bug 343628):
* Since we're removing the event target, if the user double-clicks
* the button, the dblclick event will be dispatched with the tabbar
* as its event target (and explicit/originalTarget), which treats
* that as a mouse gesture for opening a new tab.
* In this context, we're manually blocking the dblclick event.
*/
// Reset flags at the beginning of a series of clicks:
if (event.detail == 1) {
this.flagClickOnCloseButton = false;
this.flagActivateTabOrClickOnTabbar = false;
}
this.blockCloseButtonOnDblclick = this.flagActivateTabOrClickOnTabbar;
this._blockDblClick = this.flagClickOnCloseButton;
// Set flags:
let eventTargetIsCloseButton =
event.originalTarget.classList.contains("tab-close-button");
this.flagClickOnCloseButton = eventTargetIsCloseButton;
this.flagActivateTabOrClickOnTabbar =
((!eventTargetIsCloseButton && event.detail == 1) ||
event.originalTarget.localName == "box");
]]></handler>
<handler event="click" button="0"><![CDATA[
// See comment in the "mousedown" event handler of the
// tabbrowser-tabs binding.
if (event.originalTarget.classList.contains("tab-close-button") &&
!this.blockCloseButtonOnDblclick) {
gBrowser.removeTab(document.getBindingParent(event.originalTarget),
{animate: true, byMouse: true,});
this._blockDblClick = true;
}
]]></handler>
<handler event="click" button="1"><![CDATA[
if (event.target.localName == "tab") {
if (this.childNodes.length > 1 || !this._closeWindowWithLastTab)
this.tabbrowser.removeTab(event.target, {animate: true, byMouse: true});
@ -4679,63 +4738,6 @@
<binding id="tabbrowser-close-tab-button"
extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image">
<handlers>
<handler event="click" button="0"><![CDATA[
var bindingParent = document.getBindingParent(this);
var tabContainer = bindingParent.parentNode;
/* The only sequence in which a second click event (i.e. dblclik)
* can be dispatched on an in-tab close button is when it is shown
* after the first click (i.e. the first click event was dispatched
* on the tab). This happens when we show the close button only on
* the active tab. (bug 352021)
* The only sequence in which a third click event can be dispatched
* on an in-tab close button is when the tab was opened with a
* double click on the tabbar. (bug 378344)
* In both cases, it is most likely that the close button area has
* been accidentally clicked, therefore we do not close the tab.
*
* We don't want to ignore processing of more than one click event,
* though, since the user might actually be repeatedly clicking to
* close many tabs at once.
*/
if (event.detail > 1 && !this._ignoredClick) {
this._ignoredClick = true;
return;
}
// Reset the "ignored click" flag
this._ignoredClick = false;
tabContainer.tabbrowser.removeTab(bindingParent, {animate: true, byMouse: true});
tabContainer._blockDblClick = true;
/* XXXmano hack (see bug 343628):
* Since we're removing the event target, if the user
* double-clicks this button, the dblclick event will be dispatched
* with the tabbar as its event target (and explicit/originalTarget),
* which treats that as a mouse gesture for opening a new tab.
* In this context, we're manually blocking the dblclick event
* (see dblclick handler).
*/
var clickedOnce = false;
function enableDblClick(event) {
var target = event.originalTarget;
if (target.className == 'tab-close-button')
target._ignoredClick = true;
if (!clickedOnce) {
clickedOnce = true;
return;
}
tabContainer._blockDblClick = false;
tabContainer.removeEventListener("click", enableDblClick, true);
}
tabContainer.addEventListener("click", enableDblClick, true);
]]></handler>
<handler event="dblclick" button="0" phase="capturing">
// for the one-close-button case
event.stopPropagation();
</handler>
<handler event="dragstart">
event.stopPropagation();
</handler>