Bug 1600955 - Port |Bug 501426 - make the open tabs in background pref be named mail.tabs.loadInBackground and allow overriding default for context/middle click with the shift key| to SeaMonkey. r=frg
authorIan Neal <iann_cvs@blueyonder.co.uk>
Sun, 05 Jan 2020 22:09:13 +0100
changeset 37192 fa0098e6b23f110a2d74b93745321ebcbeb85fbc
parent 37191 e5e31792c53c86ffaea936104d37438bdf28d579
child 37193 d56158f2a5925c00acbb3b0e84ec71b6747c9392
push id2552
push userclokep@gmail.com
push dateMon, 10 Feb 2020 21:24:16 +0000
treeherdercomm-beta@f95a6f4408a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfrg
bugs1600955, 501426
Bug 1600955 - Port |Bug 501426 - make the open tabs in background pref be named mail.tabs.loadInBackground and allow overriding default for context/middle click with the shift key| to SeaMonkey. r=frg
suite/app/profile/suite-prefs.js
suite/locales/en-US/chrome/common/help/mailnews_preferences.xhtml
suite/locales/en-US/chrome/mailnews/pref/pref-mailnews.dtd
suite/mailnews/components/prefs/content/pref-mailnews.xul
suite/mailnews/content/mailWindowOverlay.xul
suite/mailnews/content/msgMail3PaneWindow.js
suite/mailnews/content/tabmail.js
suite/mailnews/content/tabmail.xml
suite/mailnews/content/threadPane.js
--- a/suite/app/profile/suite-prefs.js
+++ b/suite/app/profile/suite-prefs.js
@@ -354,16 +354,20 @@ pref("network.predictor.enabled", false)
 // To allow images to be inserted into a composition with an auth prompt, we
 // need the following two.
 pref("network.auth.subresource-img-cross-origin-http-auth-allow", true);
 // This pref is also needed for showing the caldav auth prompt.
 pref("network.auth.non-web-content-triggered-resources-http-auth-allow", true);
 
 pref("mail.biff.show_new_alert",     true);
 
+// If messages or folders are opened using the context menu or a middle click,
+// should we open them in the foreground or in the background?
+pref("mail.tabs.loadInBackground", true);
+
 pref("mailnews.ui.deleteMarksRead", true);
 pref("mailnews.ui.deleteAlwaysSelectedMessages", false);
 
 // The maximum amount of decoded image data we'll willingly keep around (we
 // might keep around more than this, but we'll try to get down to this value).
 // (This is intentionally on the high side; see bugs 746055 and 768015.)
 pref("image.mem.max_decoded_image_kb", 256000);
 
--- a/suite/locales/en-US/chrome/common/help/mailnews_preferences.xhtml
+++ b/suite/locales/en-US/chrome/common/help/mailnews_preferences.xhtml
@@ -70,16 +70,19 @@
     before leaving a folder when you reenter a folder.</li>
   <li><strong>Preserve threading when sorting messages</strong>: Select this
     option if you want &brandShortName; to preserve the threaded message
     grouping
     <a href="mailnews_using_mail.xhtml#sorting_and_threading_messages">when
     sorting messages</a>. If it is not selected, &brandShortName; automatically
     displays the messages unthreaded when you sort them by clicking on the
     column headers.</li>
+  <li><strong>Switch to new tabs when opened</strong>: Select this to make
+    &brandShortName; switch to the new tab when opened using <q>Open in New
+    Tab</q> or <q>Open Message in New Tab</q> context menu options.</li>
   <li><strong>Only check for new mail after opening Mail &amp;
     Newsgroups</strong>: By default, &brandShortName; checks for new messages
     even if only a browser window is open. Choose this option if you want to
     delay checking for new messages until after the Mail &amp; Newsgroups window
     has been opened at least once (be it automatically <a
     href="cs_nav_prefs_appearance.xhtml#appearance">on startup</a> or
     manually).</li>
   <li class="win"><strong>Make &brandShortName; the default application
--- a/suite/locales/en-US/chrome/mailnews/pref/pref-mailnews.dtd
+++ b/suite/locales/en-US/chrome/mailnews/pref/pref-mailnews.dtd
@@ -3,16 +3,18 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <!ENTITY pref.mailnews.title              "Mail &amp; Newsgroups">
 <!ENTITY generalSettings.caption          "General Settings">
 <!ENTITY confirmMove.label                "Confirm when moving folders to the Trash">
 <!ENTITY confirmMove.accesskey            "C">
 <!ENTITY preserveThreading.label          "Preserve threading when sorting messages">
 <!ENTITY preserveThreading.accesskey      "v">
+<!ENTITY loadInBackground.label           "Switch to new tabs when opened">
+<!ENTITY loadInBackground.accesskey       "t">
 <!ENTITY mailBiffOnNewWindow.label        "Only check for new mail after opening Mail &amp; Newsgroups">
 <!ENTITY mailBiffOnNewWindow.accesskey    "O">
 
 <!ENTITY defaultMailSettings.description  "Make &brandShortName; the default application for:">
 <!ENTITY setDefaultMail.label             "Mail">
 <!ENTITY setDefaultMail.accesskey         "M">
 <!ENTITY setDefaultNews.label             "News">
 <!ENTITY setDefaultNews.accesskey         "N">
--- a/suite/mailnews/components/prefs/content/pref-mailnews.xul
+++ b/suite/mailnews/components/prefs/content/pref-mailnews.xul
@@ -22,16 +22,19 @@
     <preferences id="mailnews_preferences">
       <preference id="mailnews.confirm.moveFoldersToTrash"
                   name="mailnews.confirm.moveFoldersToTrash" type="bool"/>
       <preference id="mailnews.remember_selected_message"
                   name="mailnews.remember_selected_message" type="bool"/>
       <preference id="mailnews.thread_pane_column_unthreads"
                   name="mailnews.thread_pane_column_unthreads"
                   inverted="true" type="bool"/>
+      <preference id="mail.tabs.loadInBackground"
+                  name="mail.tabs.loadInBackground"
+                  inverted="true" type="bool"/>
       <preference id="mailnews.start_page.enabled"
                   onchange="this.parentNode.parentNode.startPageCheck();"
                   name="mailnews.start_page.enabled" type="bool"/>
       <preference id="mailnews.start_page.url"
                   name="mailnews.start_page.url" type="wstring"/>
       <preference id="mail.biff.on_new_window"
                   name="mail.biff.on_new_window" inverted="true" type="bool"/>
       <preference id="network.protocol-handler.external.mailto"
@@ -72,16 +75,23 @@
       <hbox align="center">
         <checkbox id="mailPreserveThreading"
                   label="&preserveThreading.label;"
                   accesskey="&preserveThreading.accesskey;"
                   preference="mailnews.thread_pane_column_unthreads"/>
       </hbox>
 
       <hbox align="center">
+        <checkbox id="loadInBackground"
+                  label="&loadInBackground.label;"
+                  accesskey="&loadInBackground.accesskey;"
+                  preference="mail.tabs.loadInBackground"/>
+      </hbox>
+
+      <hbox align="center">
         <checkbox id="mailBiffOnNewWindow"
                   label="&mailBiffOnNewWindow.label;"
                   accesskey="&mailBiffOnNewWindow.accesskey;"
                   preference="mail.biff.on_new_window"/>
       </hbox>
 
       <vbox id="defaultMailPrefs" hidden="true">
         <separator class="thin"/>
--- a/suite/mailnews/content/mailWindowOverlay.xul
+++ b/suite/mailnews/content/mailWindowOverlay.xul
@@ -397,17 +397,17 @@
          onpopuphiding="if (event.target == this) FolderPaneOnPopupHiding();">
     <menuitem id="folderPaneContext-getMessages"
               label="&folderContextGetMessages.label;"
               accesskey="&folderContextGetMessages.accesskey;"
               oncommand="MsgGetMessage();"/>
     <menuitem id="folderPaneContext-openNewTab"
               label="&folderContextOpenNewTab.label;"
               accesskey="&folderContextOpenNewTab.accesskey;"
-              oncommand="MsgOpenNewTabForFolder();"/>
+              oncommand="FolderPaneContextMenuNewTab(event);"/>
     <menuitem id="folderPaneContext-openNewWindow"
               label="&folderContextOpenNewWindow.label;"
               accesskey="&folderContextOpenNewWindow.accesskey;"
               oncommand="MsgOpenNewWindowForFolder(null,-1);"/>
     <menuitem id="folderPaneContext-searchMessages"
               label="&folderContextSearchMessages.label;"
               accesskey="&folderContextSearchMessages.accesskey;"
               oncommand="gFolderTreeController.searchMessages();"/>
@@ -494,17 +494,17 @@
     <menuseparator id="mailContext-sep-link"/>
     <menuitem id="context-selectall"/>
     <menuitem id="context-copy"/>
     <menuitem id="context-searchselect"
               oncommand="MsgOpenSearch(gContextMenu.searchSelected(), event);"/>
     <menuitem id="mailContext-openNewTab"
               label="&contextOpenNewTab.label;"
               accesskey="&contextOpenNewTab.accesskey;"
-              oncommand="MsgOpenNewTabForMessage();"/>
+              oncommand="OpenMessageInNewTab(event);"/>
     <menuitem id="mailContext-openNewWindow"
               label="&contextOpenNewWindow.label;"
               accesskey="&contextOpenNewWindow.accesskey;"
               oncommand="MsgOpenNewWindowForMessage();"/>
     <menuseparator id="mailContext-sep-open"/>
     <menuitem id="mailContext-replySender"
               label="&contextReplySender.label;"
               accesskey="&contextReplySender.accesskey;"
--- a/suite/mailnews/content/msgMail3PaneWindow.js
+++ b/suite/mailnews/content/msgMail3PaneWindow.js
@@ -1192,28 +1192,35 @@ function TreeOnMouseDown(event)
   gRightMouseButtonDown = event.button == kMouseButtonRight;
   if (!gRightMouseButtonDown)
     gRightMouseButtonDown = AllowOpenTabOnMiddleClick() &&
                             event.button == kMouseButtonMiddle;
   if (gRightMouseButtonDown)
     ChangeSelectionWithoutContentLoad(event, event.target.parentNode);
 }
 
+function FolderPaneContextMenuNewTab(event) {
+  var bgLoad = Services.prefs.getBoolPref("mail.tabs.loadInBackground");
+  if (event.shiftKey)
+    bgLoad = !bgLoad;
+  MsgOpenNewTabForFolder(bgLoad);
+}
+
 function FolderPaneOnClick(event)
 {
   // usually, we're only interested in tree content clicks, not scrollbars etc.
   if (event.originalTarget.localName != "treechildren")
     return;
 
   // we may want to open the folder in a new tab on middle click
   if (event.button == kMouseButtonMiddle)
   {
     if (AllowOpenTabOnMiddleClick())
     {
-      MsgOpenNewTabForFolder();
+      FolderPaneContextMenuNewTab(event);
       RestoreSelectionWithoutContentLoad(GetFolderTree());
       return;
     }
   }
 
   // otherwise, we only care about left click events
   if (event.button != kMouseButtonLeft)
     return;
@@ -1237,32 +1244,40 @@ function FolderPaneOnClick(event)
 }
 
 function FolderPaneDoubleClick(folderIndex, event)
 {
   // In tabmail land, lazyness is dead!
   // We either open the folder in a tab or a new window...
   if (AllowOpenTabOnDoubleClick())
   {
-    MsgOpenNewTabForFolder();
+    FolderPaneContextMenuNewTab(event);
   }
   else
   {
     let folderResource = GetFolderResource(GetFolderTree(), folderIndex);
     // Open a new msg window only if we are double clicking on
     // folders or newsgroups.
     MsgOpenNewWindowForFolder(folderResource.Value, nsMsgKey_None);
   }
 
   // Double-clicking should not toggle the open/close state of the folder.
   // This will happen if we don't prevent the event from bubbling to the
   // default handler in tree.xml.
   event.stopPropagation();
 }
 
+function OpenMessageInNewTab(event) {
+  var bgLoad = Services.prefs.getBoolPref("mail.tabs.loadInBackground");
+  if (event.shiftKey)
+    bgLoad = !bgLoad;
+
+  MsgOpenNewTabForMessage(bgLoad);
+}
+
 function ChangeSelection(tree, newIndex)
 {
     if(newIndex >= 0)
     {
         tree.view.selection.select(newIndex);
         tree.treeBoxObject.ensureRowIsVisible(newIndex);
     }
 }
--- a/suite/mailnews/content/tabmail.js
+++ b/suite/mailnews/content/tabmail.js
@@ -32,21 +32,22 @@ var gMailNewsTabsType =
   modes:
   {
     "3pane":
     {
       isDefault: true,
       type: "3pane",
 
       // aTabInfo belongs to the newly created tab,
-      // aModeBits is a combination of kTabShow* layout bits (or null),
-      // aFolderURI designates the folder to select (or null)
-      // aMsgHdr designates the message to select (or null)
-      openTab: function(aTabInfo, aModeBits, aFolderURI, aMsgHdr)
-      {
+      // aArgs can contain:
+      // * modeBits is a combination of kTabShow* layout bits (or null),
+      // * folderURI designates the folder to select (or null)
+      // * msgHdr designates the message to select (or null)
+      openTab: function(aTabInfo, {modeBits: aModeBits, folderURI: aFolderURI,
+                                   msgHdr: aMsgHdr}) {
         // clone the current 3pane state before overriding parts of it
         this.saveTabState(aTabInfo);
 
         // aModeBits must have at least one bit set
         // if not, we just copy the current state
         let cloneMode = !aModeBits;
         if (cloneMode)
           aModeBits = this.getCurrentModeBits() || kTabModeFolder;
@@ -520,34 +521,31 @@ var gMailNewsTabsType =
 //  tabmail support methods
 //
 
 function GetTabMail()
 {
   return document.getElementById("tabmail");
 }
 
-function MsgOpenNewTab(aType, aModeBits)
-{
+function MsgOpenNewTab(aType, aModeBits, aBackground) {
   // duplicate the current tab
   var tabmail = GetTabMail();
   if (tabmail)
-    tabmail.openTab(aType, aModeBits);
+    tabmail.openTab(aType, {modeBits: aModeBits, background: aBackground});
 }
 
-function MsgOpenNewTabForFolder()
-{
+function MsgOpenNewTabForFolder(aBackground) {
   // open current folder in full 3pane tab
-  MsgOpenNewTab("3pane", kTabModeFolder);
+  MsgOpenNewTab("3pane", kTabModeFolder, aBackground);
 }
 
-function MsgOpenNewTabForMessage()
-{
+function MsgOpenNewTabForMessage(aBackground) {
   // open current message in message tab
-  MsgOpenNewTab("3pane", kTabModeMessage);
+  MsgOpenNewTab("3pane", kTabModeMessage, aBackground);
 }
 
 // A Thunderbird compatibility function called from e.g. newsblog.
 // We ignore aHandlerRegExp as it is not needed by SeaMonkey.
 function openContentTab(aUrl, aWhere, aHandlerRegExp)
 {
   openUILinkIn(aUrl, aWhere);
 }
--- a/suite/mailnews/content/tabmail.xml
+++ b/suite/mailnews/content/tabmail.xml
@@ -32,19 +32,22 @@
     -
     - From a javascript perspective, there are three types of code that we
     -  expect to interact with:
     - 1) Code that wants to open new tabs.
     - 2) Code that wants to contribute one or more varieties of tabs.
     - 3) Code that wants to monitor to know when the active tab changes.
     -
     - Consumer code should use the following methods:
-    - * openTab(aTabModeName, arguments...): Open a tab of the given "mode",
-    -   passing the provided arguments.  The tab type author should tell you
-    -   the modes they implement and the required/optional arguments.
+    - * openTab(aTabModeName, aArgs): Open a tab of the given "mode",
+    -   passing the provided arguments as an object.  The tab type author
+    -   should tell you the modes they implement and the required/optional
+    -   arguments.
+    -   One of the arguments you can pass is "background": if this is true,
+    -   the tab will be loaded in the background.
     - * setTabTitle([aOptionalTabInfo]): Tells us that the title of the current
     -   tab (if no argument is provided) or provided tab needs to be updated.
     -   This will result in a call to the tab mode's logic to update the title.
     -   In the event this is not for the current tab, the caller is responsible
     -   for ensuring that the underlying tab mode is capable of providing a tab
     -   title when it is in the background.
     - * removeCurrentTab(): Close the current tab.
     - * removeTab(aTabElement): Close the tab whose tabmail-tab bound
@@ -88,32 +91,33 @@
     -     Generally, this would be the same as the mode name, but you can do as
     -     you please.
     - * isDefault: This should only be present and should be true for the tab
     -     mode that is the tab displayed automatically on startup.
     - * maxTabs: The maximum number of this mode that can be opened at a time.
     -     If this limit is reached, any additional calls to openTab for this
     -     mode will simply result in the first existing tab of this mode being
     -     displayed.
-    - * shouldSwitchTo(arguments...): Optional function. Called when
-    -     openTab is called on the top-level tabmail binding. It is used to
-    -     decide if the openTab function should switch to an existing tab or
-    -     actually open a new tab.
+    - * shouldSwitchTo(aArgs): Optional function. Called when openTab is called
+    -     on the top-level tabmail binding. It is used to decide if the openTab
+    -     function should switch to an existing tab or actually open a new tab.
     -     If the openTab function should switch to an existing tab, return the
     -     index of that tab; otherwise return -1.
-    - * openTab(aTabInfo, arguments...): Called when a tab of the given mode is
-    -     in the process of being opened.  aTabInfo will have its "mode"
-    -     attribute set to the mode definition of the tab mode being opened.
-    -     You should set the "title" attribute on it, and may set any other
-    -     attributes you wish for your own use in subsequent functions.  Note
-    -     that 'this' points to the tab type definition, not the mode definition
-    -     as you might expect.  This allows you to place common logic code on
-    -     the tab type for use by multiple modes and to defer to it.  Any
-    -     arguments provided to the caller of tabmail.openTab will be passed to
-    -     your function as well.
+    -     aArgs is a set of named parameters (the ones that are later passed to
+    -     openTab).
+    - * openTab(aTabInfo, aArgs): Called when a tab of the given mode is in the
+    -     process of being opened.  aTabInfo will have its "mode" attribute
+    -     set to the mode definition of the tab mode being opened. You should
+    -     set the "title" attribute on it, and may set any other attributes
+    -     you wish for your own use in subsequent functions.  Note that 'this'
+    -     points to the tab type definition, not the mode definition as you
+    -     might expect.  This allows you to place common logic code on the
+    -     tab type for use by multiple modes and to defer to it.  Any arguments
+    -     provided to the caller of tabmail.openTab will be passed to your
+    -     function as well, including background.
     - * canCloseTab(aTabInfo): Optional function.
     -     Return true (false) if the tab is (not) allowed to close.
     -     A tab's default permission is stored in aTabInfo.canClose.
     - * closeTab(aTabInfo): Called when aTabInfo is being closed.  The tab need
     -     not be currently displayed.  You are responsible for properly cleaning
     -     up any state you preserved in aTabInfo.
     - * saveTabState(aTabInfo): Called when aTabInfo is being switched away from
     -     so that you can preserve its state on aTabInfo.  This is primarily for
@@ -357,49 +361,54 @@
               }
             }
           ]]>
         </body>
       </method>
 
       <method name="openTab">
         <parameter name="aTabModeName"/>
-        <!-- parameter name="aMoreParameters..."/-->
+        <parameter name="aArgs"/>
         <body>
           <![CDATA[
             if (!aTabModeName)
               aTabModeName = this.currentTabInfo.mode.type;
 
             let tabMode = this.tabModes[aTabModeName];
             // if we are already at our limit for this mode, show an existing one
             if (tabMode.tabs.length == tabMode.maxTabs)
             {
               // show the first tab of this mode
               this.tabContainer.selectedIndex = this.tabInfo.indexOf(tabMode.tabs[0]);
               return;
             }
 
+            // Do this so that we don't generate strict warnings.
+            let background = ("background" in aArgs) && aArgs.background;
+
             // If the mode wants us to, we should switch to an existing tab
-            // rather than open a new one.
+            // rather than open a new one. We shouldn't switch to the tab if
+            // we're opening it in the background, though.
             let shouldSwitchToFunc = tabMode.shouldSwitchTo ||
                                      tabMode.tabType.shouldSwitchTo;
 
             if (shouldSwitchToFunc)
             {
-              let args = Array.prototype.slice.call(arguments, 1);
-              let tabIndex = shouldSwitchToFunc.apply(tabMode.tabType, args);
+              let tabIndex = shouldSwitchToFunc.apply(tabMode.tabType, [aArgs]);
               if (tabIndex >= 0)
               {
-                this.selectTabByIndex(tabIndex);
+                if (!background)
+                  this.selectTabByIndex(tabIndex);
                 return;
               }
             }
 
-            // we need to save the state before it gets corrupted
-            this.saveCurrentTabState();
+            if (!background)
+              // we need to save the state before it gets corrupted
+              this.saveCurrentTabState();
 
             let tabInfo = {mode: tabMode, canClose: true};
             tabMode.tabs.push(tabInfo);
 
             let t = document.createElementNS(
               "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
               "tab");
             t.setAttribute("crop", "end");
@@ -417,29 +426,28 @@
             {
               this.mStripVisible = true;
               this.tabContainer._updateCloseButtons();
             }
 
             let oldPanel = this.panelContainer.selectedPanel;
 
             // Open new tabs in the background?
-            let switchToNewTab = !this.mPrefs.getBoolPref("browser.tabs.loadInBackground");
-            tabInfo.switchToNewTab = switchToNewTab;
+            tabInfo.switchToNewTab = !background;
 
             // the order of the following statements is important
             let oldTabInfo = this.currentTabInfo;
             this.tabInfo[this.tabContainer.childNodes.length - 1] = tabInfo;
 
-            if (switchToNewTab)
-            {
+            if (!background) {
               this.currentTabInfo = tabInfo;
               // this has a side effect of calling updateCurrentTab, but our
               // setting currentTabInfo above will cause it to take no action.
-              this.tabContainer.selectedIndex = this.tabContainer.childNodes.length - 1;
+              this.tabContainer.selectedIndex =
+                this.tabContainer.childNodes.length - 1;
             }
             // make sure we are on the right panel
             let selectedPanel;
             if (tabInfo.mode.tabType.perTabPanel)
             {
               // should we create the element for them, or will they do it?
               if (typeof(tabInfo.mode.tabType.perTabPanel) == "string")
               {
@@ -453,45 +461,41 @@
               }
               this.panelContainer.appendChild(tabInfo.panel);
               selectedPanel = tabInfo.panel;
             }
             else
             {
               selectedPanel = tabInfo.mode.tabType.panel;
             }
-            if (switchToNewTab)
+            if (!background)
               this.panelContainer.selectedPanel = selectedPanel;
 
             oldPanel.removeAttribute("selected");
             this.panelContainer.selectedPanel.setAttribute("selected", "true");
 
             let tabOpenFunc = tabInfo.mode.openTab ||
                               tabInfo.mode.tabType.openTab;
-            let args = [tabInfo].concat(Array.prototype.slice.call(arguments, 1));
             if (tabOpenFunc)
-              tabOpenFunc.apply(tabInfo.mode.tabType, args);
+              tabOpenFunc.apply(tabInfo.mode.tabType, [tabInfo, aArgs]);
 
-            if (!switchToNewTab)
-            {
+            if (background) {
               // if the new tab isn't made current,
               // its title won't change automatically
               this.setTabTitle(tabInfo);
             }
 
-            if (this.tabMonitors.length)
-            {
-              if (switchToNewTab)
-                for (let tabMonitor of this.tabMonitors)
-                  tabMonitor.onTabSwitched(tabInfo, oldTabInfo);
+            if (!background && this.tabMonitors.length) {
+              for (let tabMonitor of this.tabMonitors)
+                tabMonitor.onTabSwitched(tabInfo, oldTabInfo);
             }
 
             t.setAttribute("label", tabInfo.title);
-            if (switchToNewTab)
-            {
+
+            if (!background) {
               let docTitle = tabInfo.title;
               if (AppConstants.platform != "macosx") {
                 docTitle += " - " + gBrandBundle.getString("brandFullName");
               }
               document.title = docTitle;
 
               // Update the toolbar status - we don't need to do menus as they
               // do themselves when we open them.
@@ -1473,17 +1477,17 @@
           let bindingParent = document.getBindingParent(this);
           if (bindingParent)
           {
             let tabmail = document.getBindingParent(bindingParent);
             if (bindingParent.localName == "tabs")
             {
               // new-tab-button only appears in the tabstrip
               // duplicate the current tab
-              tabmail.openTab();
+              tabmail.openTab("", {});
             }
           }
         ]]>
       </handler>
       <handler event="dblclick" button="0" phase="capturing">
         <![CDATA[
           event.stopPropagation();
         ]]>
--- a/suite/mailnews/content/threadPane.js
+++ b/suite/mailnews/content/threadPane.js
@@ -14,17 +14,17 @@ function ThreadPaneOnClick(event)
   // we may want to open the message in a new tab on middle click
   if (event.button == kMouseButtonMiddle)
   {
     if (t.localName == "treechildren" && AllowOpenTabOnMiddleClick())
     {
       // we don't allow new tabs in the search dialog
       if (document.documentElement.id != "searchMailWindow")
       {
-        MsgOpenNewTabForMessage();
+        OpenMessageInNewTab(event);
         RestoreSelectionWithoutContentLoad(GetThreadTree());
       }
       return;
     }
   }
 
   // otherwise, we only care about left click events
   if (event.button != kMouseButtonLeft)
@@ -46,17 +46,17 @@ function ThreadPaneOnClick(event)
     var cell = tree.treeBoxObject.getCellAt(event.clientX, event.clientY);
     if (cell.row == -1)
       return;
 
     // If the cell is in a "cycler" column or if the user double clicked on the
     // twisty, don't open the message in a new window.
     if (event.detail == 2 && !cell.col.cycler && (cell.childElt != "twisty"))
     {
-      ThreadPaneDoubleClick();
+      ThreadPaneDoubleClick(event);
       // Double clicking should not toggle the open/close state of the thread.
       // This will happen if we don't prevent the event from bubbling to the
       // default handler in tree.xml.
       event.stopPropagation();
     }
     else if (cell.col.id == "junkStatusCol")
     {
       MsgJunkMailInfo(true);
@@ -173,45 +173,44 @@ function HandleColumnClick(columnID)
       MsgReverseSortThreadPane();
     }
     else {
       MsgSortThreadPane(sortType);
     }
   }
 }
 
-function ThreadPaneDoubleClick()
-{
+function ThreadPaneDoubleClick(event) {
   const nsMsgFolderFlags = Ci.nsMsgFolderFlags;
   if (IsSpecialFolderSelected(nsMsgFolderFlags.Drafts, true))
   {
     MsgComposeDraftMessage();
   }
   else if(IsSpecialFolderSelected(nsMsgFolderFlags.Templates, true))
   {
     ComposeMsgByType(Ci.nsIMsgCompType.Template, null,
                      Ci.nsIMsgCompFormat.Default);
   }
   else if (AllowOpenTabOnDoubleClick() &&
            document.documentElement.id != "searchMailWindow")
   {        // we don't allow new tabs in the search dialog
     // open the message in a new tab on double click
-    MsgOpenNewTabForMessage();
+    OpenMessageInNewTab(event);
     RestoreSelectionWithoutContentLoad(GetThreadTree());
   }
   else
   {
     MsgOpenSelectedMessages();
   }
 }
 
 function ThreadPaneKeyPress(event)
 {
   if (event.keyCode == KeyEvent.DOM_VK_RETURN)
-    ThreadPaneDoubleClick();
+    ThreadPaneDoubleClick(event);
 }
 
 function MsgSortByThread()
 {
   var dbview = GetDBView();
   dbview.viewFlags |= nsMsgViewFlagsType.kThreadedDisplay;
   dbview.viewFlags &= ~nsMsgViewFlagsType.kGroupBySort;
   MsgSortThreadPane('byDate');