Bug 1546332 - [de-xbl] convert tabmail-tab binding to custom element. r=mkmelin CLOSED TREE
authorKhushil Mistry <khushil324@gmail.com>
Wed, 29 May 2019 09:18:00 +0200
changeset 35711 69ac929f4cbbe773fa321c0d501bb7731dcad62f
parent 35710 df4dd9bfa02d68e4c4a9e7a933d46a88bacf899e
child 35712 5c0f43def1f3bcb2f0a487a006338ef056e084b2
push id392
push userclokep@gmail.com
push dateMon, 02 Sep 2019 20:17:19 +0000
reviewersmkmelin
bugs1546332
Bug 1546332 - [de-xbl] convert tabmail-tab binding to custom element. r=mkmelin CLOSED TREE
mail/base/content/mailWindowOverlay.js
mail/base/content/messenger.xul
mail/base/content/tabbrowser-tab.js
mail/base/content/tabmail.css
mail/base/content/tabmail.xml
mail/base/jar.mn
--- a/mail/base/content/mailWindowOverlay.js
+++ b/mail/base/content/mailWindowOverlay.js
@@ -1739,32 +1739,16 @@ function MsgSaveAsFile() {
   SaveAsFile(gFolderDisplay.selectedMessageUris);
 }
 
 function MsgSaveAsTemplate() {
   if (gFolderDisplay.selectedCount == 1)
     SaveAsTemplate(gFolderDisplay.selectedMessageUris[0]);
 }
 
-function CreateToolbarTooltip(document, event) {
-  event.stopPropagation();
-  var tn = document.tooltipNode;
-  if (tn.localName != "tab")
-    return false; // Not a tab, so cancel the tooltip.
-  if ("mOverCloseButton" in tn && tn.mOverCloseButton) {
-     event.target.setAttribute("label", tn.getAttribute("closetabtext"));
-     return true;
-  }
-  if (tn.hasAttribute("label")) {
-    event.target.setAttribute("label", tn.getAttribute("label"));
-    return true;
-  }
-  return false;
-}
-
 function MsgOpenNewWindowForFolder(folderURI, msgKeyToSelect) {
   if (folderURI) {
     window.openDialog("chrome://messenger/content/", "_blank",
                       "chrome,all,dialog=no", folderURI, msgKeyToSelect);
     return;
   }
 
   // If there is a right-click happening, gFolderTreeView.getSelectedFolders()
--- a/mail/base/content/messenger.xul
+++ b/mail/base/content/messenger.xul
@@ -146,16 +146,17 @@
 <script src="chrome://communicator/content/utilityOverlay.js"/>
 <script src="chrome://messenger/content/quickFilterBar.js"/>
 <script src="chrome://messenger/content/newmailaccount/uriListener.js"/>
 <script src="chrome://messenger/content/chat/chat-conversation-info.js"/>
 <script src="chrome://gloda/content/autocomplete-richlistitem.js"/>
 <script src="chrome://messenger/content/chat/chat-contact.js"/>
 <script src="chrome://messenger/content/chat/chat-group.js"/>
 <script src="chrome://messenger/content/chat/chat-imconv.js"/>
+<script src="chrome://messenger/content/tabbrowser-tab.js"/>
 #ifdef XP_MACOSX
 <script src="chrome://messenger/content/macMessengerMenu.js"/>
 <script src="chrome://global/content/macWindowMenu.js"/>
 #endif
 
 <!-- move needed functions into a single js file -->
 <script src="chrome://messenger/content/threadPane.js"/>
 
@@ -387,17 +388,17 @@
             align="end"
             setfocus="false"
             onclick="document.getElementById('tabmail').onTabClick(event);"
             class="tabmail-tabs"
             tooltip="tabmail-tabs-tooltip"
             alltabsbutton="alltabs-button"
             collapsetoolbar="tabs-toolbar"
             tabtoolbar="tabbar-toolbar">
-            <tab selected="true" validate="never" type="folder"
+            <tab is="tabmail-tab" selected="true" validate="never" type="folder"
                  maxwidth="250" width="0" minwidth="100" flex="100"
                  class="tabmail-tab" crop="end" linkedpanel="mailContent"/>
       </tabs>
 
       <!-- Use of this element for extensions is deprecated! Current
            extensions should add to #mail-toolbox and add a toolbar item to
            #tabbar-toolbar below. -->
       <hbox id="tabmail-buttons"/>
new file mode 100644
--- /dev/null
+++ b/mail/base/content/tabbrowser-tab.js
@@ -0,0 +1,118 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+  * License, v. 2.0. If a copy of the MPL was not distributed with this
+  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+/* global MozElements, MozXULElement */
+
+{
+  /**
+    * The MozTabmailTab widget behaves as a tab in the messenger window.
+    * It is used to navigate between different views. It displays information
+    * about the view: i.e. name and icon.
+    *
+    * @extends {MozElements.MozTab}
+    */
+  class MozTabmailTab extends MozElements.MozTab {
+    static get inheritedAttributes() {
+      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",
+      };
+    }
+
+    connectedCallback() {
+      if (this.delayConnectedCallback() || this.hasChildNodes()) {
+        return;
+      }
+
+      this.setAttribute("is", "tabmail-tab");
+      this.appendChild(MozXULElement.parseXULToFragment(`
+        <stack class="tab-stack" flex="1" closetabtext="&closeTab.label;">
+          <vbox class="tab-background">
+            <hbox class="tab-line"></hbox>
+          </vbox>
+          <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>
+          </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;
+        }
+      });
+
+      this.addEventListener("dragstart", (event) => {
+        document.dragTab = this;
+      }, true);
+
+      this.addEventListener("dragover", (event) => {
+        document.dragTab = null;
+      }, true);
+
+      this.addEventListener("mouseout", (event) => {
+        document.tab = null;
+        if (event.originalTarget.classList.contains("tab-close-button")) {
+          this.mOverCloseButton = false;
+        }
+      });
+
+      this.addEventListener("mousedown", (event) => {
+        if (event.button != 0) {
+          return;
+        }
+
+        if (this.mOverCloseButton) {
+          event.stopPropagation();
+        }
+      }, true);
+
+      this.addEventListener("contextmenu", (event) => {
+        document.popupNode = this;
+      }, true);
+
+      this.mOverCloseButton = false;
+
+      this.setAttribute("context", "tabContextMenu");
+
+      this.mCorrespondingMenuitem = null;
+
+      this.initializeAttributeInheritance();
+    }
+
+    get linkedBrowser() {
+      let tabmail = document.getElementById("tabmail");
+      let tab = tabmail._getTabContextForTabbyThing(this, false)[1];
+      return tabmail.getBrowserForTab(tab);
+    }
+
+    get mode() {
+      let tabmail = document.getElementById("tabmail");
+      let tab = tabmail._getTabContextForTabbyThing(this, false)[1];
+      return tab.mode;
+    }
+  }
+
+  MozXULElement.implementCustomInterface(MozTabmailTab, [Ci.nsIDOMXULSelectControlItemElement]);
+
+  customElements.define("tabmail-tab", MozTabmailTab, { extends: "tab" });
+}
--- a/mail/base/content/tabmail.css
+++ b/mail/base/content/tabmail.css
@@ -1,20 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #tabmail-tabs {
   -moz-binding: url("chrome://messenger/content/tabmail.xml#tabmail-tabs");
 }
 
-.tabmail-tab {
-  -moz-binding: url("chrome://messenger/content/tabmail.xml#tabmail-tab");
-}
-
 .tabmail-arrowscrollbox {
   -moz-binding: url("chrome://messenger/content/tabmail.xml#tabmail-arrowscrollbox");
 }
 
 .tabs-alltabs-popup {
   -moz-binding: url("chrome://messenger/content/tabmail.xml#tabmail-alltabs-popup");
 }
 
--- a/mail/base/content/tabmail.xml
+++ b/mail/base/content/tabmail.xml
@@ -318,23 +318,23 @@
       </field>
       <field name="unrestoredTabs" readonly="true">
         [];
       </field>
       <method name="createTooltip">
         <parameter name="event"/>
         <body><![CDATA[
           event.stopPropagation();
-          var tab = document.tooltipNode;
+          let tab = document.tab;
           if (tab.localName != "tab" || this.tabContainer.draggedTab) {
             event.preventDefault();
             return;
           }
           event.target.setAttribute("label", tab.mOverCloseButton ?
-                                             tab.getAttribute("closetabtext") :
+                                             tab.firstChild.getAttribute("closetabtext") :
                                              tab.getAttribute("label"));
 
           ]]>
         </body>
       </method>
       <method name="registerTabType">
         <parameter name="aTabType"/>
         <body><![CDATA[
@@ -535,19 +535,17 @@
           if (!background)
             // we need to save the state before it gets corrupted
             this.saveCurrentTabState();
 
           let tab = {mode: tabMode, busy: false, canClose: true,
                      thinking: false, beforeTabOpen: true, _ext: {}};
           tabMode.tabs.push(tab);
 
-          var t = document.createElementNS(
-            "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
-            "tab");
+          var t = document.createXULElement("tab", { is: "tabmail-tab" });
           tab.tabNode = t;
           t.maxWidth = this.tabContainer.mTabMaxWidth;
           t.minWidth = this.tabContainer.mTabMinWidth;
           t.width = 0;
           t.setAttribute("flex", "100");
           t.setAttribute("validate", "never");
           t.className = "tabmail-tab";
           this.tabContainer.appendChild(t);
@@ -1311,19 +1309,19 @@
           ]]>
         </body>
       </method>
       <method name="onTabClick">
         <parameter name="event"/>
         <body>
           <![CDATA[
             // a middle mouse button click on a tab is a short cut for closing a tab
-            if (event.button != 1 || event.target.localName != "tab")
+            if (event.button != 1 || document.tab.localName != "tab")
               return;
-            this.removeTabByNode(event.target);
+            this.removeTabByNode(document.tab);
             event.stopPropagation();
           ]]>
         </body>
       </method>
       <method name="setTabTitle">
         <parameter name="aTabNodeOrInfo"/>
         <body>
           <![CDATA[
@@ -1786,143 +1784,16 @@
                                     .chromeEventHandler;
           this._callTabListeners("onRefreshAttempted", [browser, ...arguments]);
         ]]></body>
       </method>
 
     </implementation>
   </binding>
 
-  <binding id="tabmail-tab"
-           extends="chrome://global/content/bindings/tabbox.xml#tab">
-    <content closetabtext="&closeTab.label;" context="tabContextMenu">
-      <xul:stack class="tab-stack" flex="1">
-        <xul:vbox xbl:inherits="pinned,selected,titlechanged"
-                  class="tab-background">
-        <xul:hbox xbl:inherits="selected=visuallyselected"
-                  class="tab-line"/>
-      </xul:vbox>
-        <xul:hbox xbl:inherits="pinned,selected,titlechanged"
-                  class="tab-content" align="center">
-          <xul:image xbl:inherits="fadein,pinned,busy,progress,selected"
-                     class="tab-throbber"
-                     role="presentation"/>
-          <xul:image xbl:inherits="validate,src=image,src,fadein,pinned,selected"
-                     class="tab-icon-image"
-                     role="presentation"/>
-          <xul:hbox class="tab-label-container"
-                    xbl:inherits="pinned,selected=visuallyselected"
-                    onoverflow="this.setAttribute('textoverflow', 'true');"
-                    onunderflow="this.removeAttribute('textoverflow');"
-                    flex="1">
-            <xul:label class="tab-text tab-label"
-                       xbl:inherits="xbl:text=label,accesskey,fadein,pinned,selected"
-                       role="presentation"/>
-          </xul:hbox>
-          <xul:image anonid="close-button"
-                     xbl:inherits="fadein,pinned,selected=visuallyselected"
-                     class="tab-close-button close-icon"/>
-        </xul:hbox>
-      </xul:stack>
-    </content>
-
-    <implementation>
-      <field name="mOverCloseButton">false</field>
-      <field name="mCorrespondingMenuitem">null</field>
-
-      <property name="linkedBrowser">
-        <getter><![CDATA[
-          let tabmail = document.getElementById("tabmail");
-          let tab = tabmail._getTabContextForTabbyThing(this, false)[1];
-          return tabmail.getBrowserForTab(tab);
-        ]]></getter>
-      </property>
-
-      <property name="mode">
-        <getter><![CDATA[
-          let tabmail = document.getElementById("tabmail");
-          let tab = tabmail._getTabContextForTabbyThing(this, false)[1];
-          return tab.mode;
-        ]]></getter>
-      </property>
-    </implementation>
-
-    <handlers>
-      <handler event="mouseover">
-        var anonid = event.originalTarget.getAttribute("anonid");
-        if (anonid == "close-button")
-          this.mOverCloseButton = true;
-      </handler>
-      <handler event="mouseout">
-        var anonid = event.originalTarget.getAttribute("anonid");
-        if (anonid == "close-button")
-          this.mOverCloseButton = false;
-      </handler>
-      <handler event="mousedown" button="0" phase="capturing">
-      <![CDATA[
-        if (this.mOverCloseButton)
-          event.stopPropagation();
-      ]]>
-      </handler>
-      <handler event="click" button="0"><![CDATA[
-        if (event.originalTarget.getAttribute("anonid") != "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.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);
-        } else { // "tabs"
-          tabbedBrowser.removeCurrentTab();
-        }
-      ]]></handler>
-      <handler event="dblclick" button="0" phase="capturing">
-        // for the one-close-button case
-        event.stopPropagation();
-      </handler>
-    </handlers>
-  </binding>
-
   <binding id="tabmail-arrowscrollbox" extends="chrome://global/content/bindings/scrollbox.xml#arrowscrollbox">
     <content>
       <xul:toolbarbutton class="scrollbutton-up"
                          xbl:inherits="orient,collapsed=notoverflowing,disabled=scrolledtostart"
                          anonid="scrollbutton-up"
                          onmousedown="_startScroll(-1);"
                          onmouseup="_stopScroll();"
                          onmouseout="_stopScroll();"/>
@@ -2336,20 +2207,20 @@
             this._stopAnimation();
         ]]></body>
       </method>
 
       <method name="_getDragTargetTab">
         <parameter name="event"/>
         <body><![CDATA[
 
-          if (event.target.localName != "tab")
+          if (document.dragTab.localName != "tab")
             return null;
 
-          let tab = event.target;
+          let tab = document.dragTab;
 
           if ((event.type != "drop") && (event.type != "dragover"))
             return tab;
 
           let tabRect = tab.getBoundingClientRect();
           if (event.screenX < tab.screenX + tabRect.width * .25)
             return null;
 
@@ -2714,17 +2585,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("tabs-closebutton")) {
+        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
@@ -2749,18 +2620,19 @@
            * 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.className == "tab-close-button")
+            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);
--- a/mail/base/jar.mn
+++ b/mail/base/jar.mn
@@ -71,16 +71,17 @@ messenger.jar:
     content/messenger/phishingDetector.js           (content/phishingDetector.js)
     content/messenger/mail-offline.js               (content/mail-offline.js)
     content/messenger/aboutDialog.css               (content/aboutDialog.css)
     content/messenger/converterDialog.css           (content/converterDialog.css)
     content/messenger/notification.css              (content/notification.css)
 *   content/messenger/messenger.css                 (content/messenger.css)
     content/messenger/search.xml                    (content/search.xml)
     content/messenger/tabmail.xml                   (content/tabmail.xml)
+    content/messenger/tabbrowser-tab.js             (content/tabbrowser-tab.js)
     content/messenger/tabmail.css                   (content/tabmail.css)
     content/messenger/statuspanel.js                (content/statuspanel.js)
     content/messenger/newTagDialog.xul              (content/newTagDialog.xul)
     content/messenger/newTagDialog.js               (content/newTagDialog.js)
     content/messenger/composerOverlay.css           (content/composerOverlay.css)
     content/messenger/threadPane.js                 (content/threadPane.js)
     content/messenger/protovis-r2.6-modded.js       (content/protovis-r2.6-modded.js)
 #ifdef XP_MACOSX