Bug 1556375 - Fix issue with tab closing. r=mkmelin
authorKhushil Mistry <khushil324@gmail.com>
Tue, 04 Jun 2019 10:32:00 +0200
changeset 35773 5116ce5bc260ce3aa7cc7c975eca2149bc14c8c6
parent 35772 cc7e364a250430cfb4ceddf7bbc0d240c7f3f136
child 35774 0e71e7bac1888f0d0871fc6542dec4b32fb5b532
push id392
push userclokep@gmail.com
push dateMon, 02 Sep 2019 20:17:19 +0000
reviewersmkmelin
bugs1556375
Bug 1556375 - Fix issue with tab closing. r=mkmelin
mail/base/content/tabbrowser-tab.js
mail/base/content/tabmail.xml
--- a/mail/base/content/tabbrowser-tab.js
+++ b/mail/base/content/tabbrowser-tab.js
@@ -19,17 +19,17 @@
       return {
         ".tab-background": "pinned,selected,titlechanged",
         ".tab-line": "selected=visuallyselected",
         ".tab-content": "pinned,selected,titlechanged",
         ".tab-throbber": "fadein,pinned,busy,progress,selected",
         ".tab-icon-image": "validate,src=image,src,fadein,pinned,selected",
         ".tab-label-container": "pinned,selected=visuallyselected",
         ".tab-text": "text=label,accesskey,fadein,pinned,selected",
-        ".tab-close-button": "fadein,pinned,selected",
+        ".tab-close-button": "fadein,pinned,selected=visuallyselected",
       };
     }
 
     connectedCallback() {
       if (this.delayConnectedCallback() || this.hasChildNodes()) {
         return;
       }
 
@@ -42,19 +42,17 @@
           <hbox class="tab-content" align="center">
             <image class="tab-throbber" role="presentation"></image>
             <image class="tab-icon-image" role="presentation"></image>
             <hbox class="tab-label-container"
                   onoverflow="this.setAttribute('textoverflow', 'true');"
                   onunderflow="this.removeAttribute('textoverflow');" flex="1">
               <label class="tab-text tab-label" role="presentation"></label>
             </hbox>
-            <toolbarbutton tabindex="-1" clickthrough="never"
-                           class="tab-close-button close-icon">
-            </toolbarbutton>
+            <image class="tab-close-button close-icon"/>
           </hbox>
         </stack>
       `, ["chrome://messenger/locale/tabmail.dtd"]));
 
       this.addEventListener("mouseover", (event) => {
         document.tab = this;
         if (event.originalTarget.classList.contains("tab-close-button")) {
           this.mOverCloseButton = true;
@@ -81,20 +79,82 @@
           return;
         }
 
         if (this.mOverCloseButton) {
           event.stopPropagation();
         }
       }, true);
 
+      this.addEventListener("click", (event) => {
+        if (event.button != 0) {
+          return;
+        }
+        if (!event.originalTarget.classList.contains("tab-close-button")) {
+          return;
+        }
+
+        let tabbedBrowser = document.getElementById("tabmail");
+        if (this.localName == "tab") {
+          // 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.
+          if (event.detail > 1) {
+            return;
+          }
+
+          tabbedBrowser.removeTabByNode(this);
+          tabbedBrowser._blockDblClick = true;
+          let tabContainer = tabbedBrowser.tabContainer;
+
+          // 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 onTabBarDblClick).
+          let clickedOnce = false;
+          let enableDblClick = function enableDblClick(event) {
+            let target = event.originalTarget;
+            if (target.classList.contains("tab-close-button")) {
+              target._ignoredClick = true;
+            }
+            if (!clickedOnce) {
+              clickedOnce = true;
+              return;
+            }
+            tabContainer._blockDblClick = false;
+            tabContainer.removeEventListener("click", enableDblClick, true);
+          };
+          tabContainer.addEventListener("click", enableDblClick, true);
+        } else { // "tabs"
+          tabbedBrowser.removeCurrentTab();
+        }
+      });
+
       this.addEventListener("contextmenu", (event) => {
         document.popupNode = this;
       }, true);
 
+      this.addEventListener("dblclick", (event) => {
+        if (event.button != 0) {
+          return;
+        }
+        // for the one-close-button case
+        event.stopPropagation();
+      }, true);
+
       this.mOverCloseButton = false;
 
       this.setAttribute("context", "tabContextMenu");
 
       this.mCorrespondingMenuitem = null;
 
       this.initializeAttributeInheritance();
     }
--- a/mail/base/content/tabmail.xml
+++ b/mail/base/content/tabmail.xml
@@ -2565,17 +2565,17 @@
       <handler event="dragexit"><![CDATA[
         this._dragTime = 0;
 
         this._tabDropIndicator.collapsed = true;
         event.stopPropagation();
 
       ]]></handler>
       <handler event="click" button="0"><![CDATA[
-        if (!event.originalTarget.classList.contains("tab-close-button")) {
+        if (!event.originalTarget.classList.contains("tabs-closebutton")) {
           return;
         }
 
         let tabbedBrowser = document.getElementById("tabmail");
         if (this.localName == "tab") {
           /* 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