Bug 495818 Zoom menu applies to the message pane rather than the browser in the selected tab. r=philringnalda
authorMark Banner <bugzilla@standard8.plus.com>
Fri, 05 Jun 2009 09:25:42 +0100
changeset 2781 d4dc984c7653697a259d32225bc6f3bd0fc739b7
parent 2780 afaecfac4fac59e302db1ecc1242cd7c4819b6e9
child 2782 1778f46c3aaf4a961e9764040f277dba87f7330b
push id2252
push userbugzilla@standard8.plus.com
push dateFri, 05 Jun 2009 08:26:33 +0000
treeherdercomm-central@d4dc984c7653 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersphilringnalda
bugs495818
Bug 495818 Zoom menu applies to the message pane rather than the browser in the selected tab. r=philringnalda
mail/base/content/mail3PaneWindowCommands.js
mail/base/content/mailWindow.js
mail/base/content/mailWindowOverlay.js
mail/base/content/mailWindowOverlay.xul
mail/base/content/messageWindow.js
mail/base/content/msgMail3PaneWindow.js
mail/base/content/specialTabs.js
mail/base/content/tabmail.xml
--- a/mail/base/content/mail3PaneWindowCommands.js
+++ b/mail/base/content/mail3PaneWindowCommands.js
@@ -224,16 +224,20 @@ var DefaultController =
       case "cmd_emptyTrash":
       case "cmd_compactFolder":
       case "button_compact":
       case "cmd_settingsOffline":
       case "cmd_selectAll":
       case "cmd_selectThread":
       case "cmd_moveToFolderAgain":
       case "cmd_selectFlagged":
+      case "cmd_fullZoomReduce":
+      case "cmd_fullZoomEnlarge":
+      case "cmd_fullZoomReset":
+      case "cmd_fullZoomToggle":
         return true;
       case "cmd_downloadFlagged":
       case "cmd_downloadSelected":
       case "cmd_synchronizeOffline":
         return MailOfflineMgr.isOnline();
 
       case "cmd_watchThread":
       case "cmd_killThread":
@@ -491,16 +495,21 @@ var DefaultController =
         if (pref.getBoolPref("mail.last_msg_movecopy_was_move"))
         {
           let loadedFolder = gFolderTreeView.getSelectedFolders()[0];
           if (!loadedFolder.canDeleteMessages)
             return false;
         }
         return pref.getCharPref("mail.last_msg_movecopy_target_uri") &&
                GetNumSelectedMessages() > 0;
+      case "cmd_fullZoomReduce":
+      case "cmd_fullZoomEnlarge":
+      case "cmd_fullZoomReset":
+      case "cmd_fullZoomToggle":
+        return IsFolderSelected() && !IsMessagePaneCollapsed();
       default:
         return false;
     }
     return false;
   },
 
   doCommand: function(command)
   {
@@ -779,16 +788,28 @@ var DefaultController =
           }
           break;
       case "cmd_selectThread":
           gDBView.doCommand(nsMsgViewCommandType.selectThread);
           break;
       case "cmd_selectFlagged":
         gDBView.doCommand(nsMsgViewCommandType.selectFlagged);
         break;
+      case "cmd_fullZoomReduce":
+        ZoomManager.reduce();
+        break;
+      case "cmd_fullZoomEnlarge":
+        ZoomManager.enlarge();
+        break;
+      case "cmd_fullZoomReset":
+        ZoomManager.reset();
+        break;
+      case "cmd_fullZoomToggle":
+        ZoomManager.toggleZoom();
+        break;
     }
   },
 
   onEvent: function(event)
   {
     // on blur events set the menu item texts back to the normal values
     if ( event == 'blur' )
     {
--- a/mail/base/content/mailWindow.js
+++ b/mail/base/content/mailWindow.js
@@ -143,17 +143,17 @@ function InitMsgWindow()
   msgWindow.windowCommands = new nsMsgWindowCommands();
   // set the domWindow before setting the status feedback and header sink objects
   msgWindow.domWindow = window;
   msgWindow.statusFeedback = statusFeedback;
   msgWindow.msgHeaderSink = messageHeaderSink;
   Components.classes["@mozilla.org/messenger/services/session;1"]
             .getService(Components.interfaces.nsIMsgMailSession)
             .AddMsgWindow(msgWindow);
-  getBrowser().docShell.allowAuth = false;
+  document.getElementById("messagepane").docShell.allowAuth = false;
   msgWindow.rootDocShell.allowAuth = true;
   msgWindow.rootDocShell.appType = Components.interfaces.nsIDocShell.APP_TYPE_MAIL;
   // Ensure we don't load xul error pages into the main window
   msgWindow.rootDocShell.useErrorPages = false;
 }
 
 // We're going to implement our status feedback for the mail window in JS now.
 // the following contains the implementation of our status feedback object
@@ -540,20 +540,23 @@ function HidingThreadPane()
   ClearThreadPane();
   GetUnreadCountElement().hidden = true;
   GetTotalCountElement().hidden = true;
   GetMessagePane().collapsed = true;
   document.getElementById("threadpane-splitter").collapsed = true;
   document.getElementById("key_toggleMessagePane").setAttribute("disabled", "true");
 }
 
-// the find toolbar needs a method called getBrowser
+// The zoom manager, view source and possibly some other functions still rely
+// on the getBrowser function.
 function getBrowser()
 {
-  return document.getElementById("messagepane");
+  let tabmail = document.getElementById('tabmail');
+  return tabmail ? tabmail.getBrowserForSelectedTab() :
+                   document.getElementById("messagepane");
 }
 
 var gCurrentDisplayDeckId = "";
 function ObserveDisplayDeckChange(event)
 {
   var selectedPanel = document.getElementById("displayDeck").selectedPanel;
   var nowSelected = selectedPanel ? selectedPanel.id : null;
   // onselect fires for every mouse click inside the deck, so ObserveDisplayDeckChange is getting called every time we click
--- a/mail/base/content/mailWindowOverlay.js
+++ b/mail/base/content/mailWindowOverlay.js
@@ -1727,16 +1727,20 @@ let mailTabType = {
     }
     else
     {
       aTab.selectedMsgId = null;
       aTab.msgSelectedFolder = gDBView.msgFolder;
     }
     if (aTab.msgSelectedFolder)
       aTab.mailView = GetMailViewForFolder(aTab.msgSelectedFolder);
+
+    // Now let other tabs have a primary browser if they want.
+    document.getElementById("messagepane").setAttribute("type",
+                                                        "content-targetable");
   },
 
   _displayFolderAndThreadPane: function(show) {
     let collapse = !show;
     let layout = pref.getIntPref("mail.pane_config.dynamic");
     if (layout == kWidePaneConfig)
     {
       document.getElementById("messengerBox").collapsed = collapse;
@@ -1799,16 +1803,20 @@ let mailTabType = {
   set folderAndThreadPaneVisible(aDesiredVisible) {
     if (aDesiredVisible != this._folderAndThreadPaneVisible) {
       this._displayFolderAndThreadPane(aDesiredVisible);
       this._folderAndThreadPaneVisible = aDesiredVisible;
     }
   },
 
   showTab: function(aTab) {
+    // Set the messagepane as the primary browser for content.
+    document.getElementById("messagepane").setAttribute("type",
+                                                        "content-primary");
+
     // restore globals
     messenger = aTab.messenger;
     gDBView = aTab.dbView;
     gSearchSession = aTab.searchSession;
 
     // restore selection in folder pane;
     let folderToSelect = gDBView ? gDBView.msgFolder : aTab.msgSelectedFolder;
     // restore view state if we had one
@@ -1884,16 +1892,21 @@ let mailTabType = {
   },
 
   doCommand: function(aTab, aCommand) {
     DefaultController.doCommand(aCommand);
   },
 
   onEvent: function(aTab, aEvent) {
     DefaultController.onEvent(aEvent);
+  },
+
+  getBrowser: function(aTab) {
+    // We currently use the messagepane element for all tab types.
+    return document.getElementById("messagepane");
   }
 };
 
 function MsgOpenNewWindowForFolder(folderURI, msgKeyToSelect)
 {
   if (folderURI) {
     window.openDialog("chrome://messenger/content/", "_blank",
                       "chrome,all,dialog=no", folderURI, msgKeyToSelect);
--- a/mail/base/content/mailWindowOverlay.xul
+++ b/mail/base/content/mailWindowOverlay.xul
@@ -137,21 +137,28 @@
 
    <command id="cmd_expandAllThreads" oncommand="goDoCommand('cmd_expandAllThreads')" disabled="true"/>
    <command id="cmd_collapseAllThreads" oncommand="goDoCommand('cmd_collapseAllThreads')" disabled="true"/>
    <command id="cmd_viewAllMsgs" oncommand="goDoCommand('cmd_viewAllMsgs')" disabled="true"/>
    <command id="cmd_viewUnreadMsgs" oncommand="goDoCommand('cmd_viewUnreadMsgs')" disabled="true"/>
    <command id="cmd_viewThreadsWithUnread" oncommand="goDoCommand('cmd_viewThreadsWithUnread')" disabled="true"/>
    <command id="cmd_viewWatchedThreadsWithUnread" oncommand="goDoCommand('cmd_viewWatchedThreadsWithUnread')" disabled="true"/>
    <command id="cmd_viewIgnoredThreads" oncommand="goDoCommand('cmd_viewIgnoredThreads')" disabled="true"/>
-   <commandset id="viewZoomCommands">
-     <command id="cmd_fullZoomReduce"  oncommand="ZoomManager.reduce()"/>
-     <command id="cmd_fullZoomEnlarge" oncommand="ZoomManager.enlarge()"/>
-     <command id="cmd_fullZoomReset"   oncommand="ZoomManager.reset()"/>
-     <command id="cmd_fullZoomToggle"  oncommand="ZoomManager.toggleZoom();"/>
+   <commandset id="viewZoomCommands"
+               commandupdater="true"
+               events="create-menu-view"
+               oncommandupdate="goUpdateMailMenuItems(this);">
+     <command id="cmd_fullZoomReduce"
+              oncommand="goDoCommand('cmd_fullZoomReduce');"/>
+     <command id="cmd_fullZoomEnlarge"
+              oncommand="goDoCommand('cmd_fullZoomEnlarge');"/>
+     <command id="cmd_fullZoomReset"
+              oncommand="goDoCommand('cmd_fullZoomReset');"/>
+     <command id="cmd_fullZoomToggle"
+              oncommand="goDoCommand('cmd_fullZoomToggle');"/>
    </commandset>
 </commandset>
 
 <commandset id="mailEditMenuItems"
             commandupdater="true"
             events="create-menu-edit"
             oncommandupdate="goUpdateMailMenuItems(this)">
 
--- a/mail/base/content/messageWindow.js
+++ b/mail/base/content/messageWindow.js
@@ -801,16 +801,20 @@ var MessageWindowController =
       case "button_print":
       case "cmd_print":
       case "cmd_printpreview":
       case "cmd_printSetup":
       case "cmd_settingsOffline":
       case "cmd_createFilterFromPopup":
       case "cmd_createFilterFromMenu":
       case "cmd_moveToFolderAgain":
+      case "cmd_fullZoomReduce":
+      case "cmd_fullZoomEnlarge":
+      case "cmd_fullZoomReset":
+      case "cmd_fullZoomToggle":
         return true;
       case "cmd_synchronizeOffline":
       case "cmd_downloadFlagged":
       case "cmd_downloadSelected":
         return MailOfflineMgr.isOnline();
       default:
         return false;
     }
@@ -904,16 +908,20 @@ var MessageWindowController =
       case "cmd_previousMsg":
       case "cmd_previousUnreadMsg":
       case "cmd_previousFlaggedMsg":
       case "cmd_findAgain":
       case "cmd_findPrevious":
       case "cmd_goForward":
       case "cmd_goBack":
       case "cmd_applyFiltersToSelection":
+      case "cmd_fullZoomReduce":
+      case "cmd_fullZoomEnlarge":
+      case "cmd_fullZoomReset":
+      case "cmd_fullZoomToggle":
         return true;
       case "button_goForward":
       case "button_goBack":
       case "cmd_goForward":
       case "cmd_goBack":
         return gDBView &&
             gDBView.navigateStatus((command == "cmd_goBack" ||
                                     command == "button_goBack")
@@ -1118,16 +1126,28 @@ var MessageWindowController =
         performNavigation(nsMsgNavigationType.forward);
         break;
       case "cmd_goBack":
         performNavigation(nsMsgNavigationType.back);
         break;
       case "cmd_applyFiltersToSelection":
         MsgApplyFiltersToSelection();
         break;
+      case "cmd_fullZoomReduce":
+        ZoomManager.reduce();
+        break;
+      case "cmd_fullZoomEnlarge":
+        ZoomManager.enlarge();
+        break;
+      case "cmd_fullZoomReset":
+        ZoomManager.reset();
+        break;
+      case "cmd_fullZoomToggle":
+        ZoomManager.toggleZoom();
+        break;
       }
   },
 
   onEvent: function(event)
   {
   }
 };
 
--- a/mail/base/content/msgMail3PaneWindow.js
+++ b/mail/base/content/msgMail3PaneWindow.js
@@ -1090,17 +1090,20 @@ function GetMessagePane()
 {
   if (!gMessagePane)
     gMessagePane = document.getElementById("messagepanebox");
   return gMessagePane;
 }
 
 function GetMessagePaneFrame()
 {
-  return window.content;
+  // We must use the message pane element directly here, as other tabs can
+  // have browser elements as well (which could be set to content-primary,
+  // which would confuse things with a window.content return).
+  return document.getElementById("messagepane").contentWindow;
 }
 
 function getMailToolbox()
 {
   return document.getElementById("mail-toolbox");
 }
 
 function FindInSidebar(currentWindow, id)
--- a/mail/base/content/specialTabs.js
+++ b/mail/base/content/specialTabs.js
@@ -58,16 +58,17 @@ var specialTabs = {
   },
 
   /**
    * A tab to show content pages.
    */
   contentTabType: {
     name: "contentTab",
     perTabPanel: "vbox",
+    lastBrowserId: 0,
     modes: {
       contentTab: {
         type: "contentTab",
         maxTabs: 10
       }
     },
     shouldSwitchTo: function onSwitchTo(aContentPage, aTitle) {
       let tabmail = document.getElementById("tabmail");
@@ -93,33 +94,99 @@ var specialTabs = {
       }
       return -1;
     },
     // XXX it would be nice to have an onload listener and set the title
     // after the load, however tabmail doesn't support that at the moment.
     openTab: function onTabOpened(aTab, aContentPage, aTitle) {
       // You can't dynamically change an iframe from a non-content to a content
       // type, therefore we dynamically create the element instead.
-      let iframe = document.createElement("iframe");
-      iframe.setAttribute("type", "content");
+      let iframe = document.createElement("browser");
+      iframe.setAttribute("type", "content-primary");
       iframe.setAttribute("flex", "1");
+      iframe.setAttribute("autocompleteenabled", false);
+      iframe.setAttribute("disablehistory", true);
+      iframe.setAttribute("id", "contentTabType" + this.lastBrowserId);
 
       aTab.panel.appendChild(iframe);
 
       iframe.setAttribute("src", aContentPage);
 
       aTab.title = aTitle;
+
+      let findbar = document.createElement("findbar");
+      findbar.setAttribute("browserid", "contentTabType" + this.lastBrowserId);
+      aTab.panel.appendChild(findbar);
+      this.lastBrowserId++;
     },
     closeTab: function onTabClosed(aTab) {
     },
     saveTabState: function onSaveTabState(aTab) {
+      aTab.panel.firstChild.setAttribute("type", "content-targetable");
     },
     showTab: function onShowTab(aTab) {
+      aTab.panel.firstChild.setAttribute("type", "content-primary");
     },
     onTitleChanged: function onTitleChanged(aTab) {
+    },
+    supportsCommand: function supportsCommand(aTab, aCommand) {
+      switch (aCommand) {
+        case "cmd_fullZoomReduce":
+        case "cmd_fullZoomEnlarge":
+        case "cmd_fullZoomReset":
+        case "cmd_fullZoomToggle":
+        case "cmd_find":
+        case "cmd_findAgain":
+        case "cmd_findPrevious":
+          return true;
+        default:
+          return false;
+      }
+    },
+    isCommandEnabled: function isCommandEnabled(aTab, aCommand) {
+      switch (aCommand) {
+        case "cmd_fullZoomReduce":
+        case "cmd_fullZoomEnlarge":
+        case "cmd_fullZoomReset":
+        case "cmd_fullZoomToggle":
+        case "cmd_find":
+        case "cmd_findAgain":
+        case "cmd_findPrevious":
+          return true;
+        default:
+          return false;
+      }
+    },
+    doCommand: function isCommandEnabled(aTab, aCommand) {
+      switch (aCommand) {
+        case "cmd_fullZoomReduce":
+          ZoomManager.reduce();
+          break;
+        case "cmd_fullZoomEnlarge":
+          ZoomManager.enlarge();
+          break;
+        case "cmd_fullZoomReset":
+          ZoomManager.reset();
+          break;
+        case "cmd_fullZoomToggle":
+          ZoomManager.toggleZoom();
+          break;
+        case "cmd_find":
+          aTab.panel.childNodes[1].onFindCommand();
+          break;
+        case "cmd_findAgain":
+          aTab.panel.childNodes[1].onFindAgainCommand(false);
+          break;
+        case "cmd_findPrevious":
+          aTab.panel.childNodes[1].onFindAgainCommand(true);
+          break;
+      }
+    },
+    getBrowser: function getBrowser(aTab) {
+      return aTab.panel.firstChild;
     }
   },
 
   /**
    * Tests whether the application has been upgraded
    * or not. Updates the pref with the latest version,
    * returns true if upgraded, false otherwise.
    */
--- a/mail/base/content/tabmail.xml
+++ b/mail/base/content/tabmail.xml
@@ -163,16 +163,20 @@
     -     isCommandEnabled and doCommand, return false otherwise.
     - * isCommandEnabled(aTab, aCommand): Called when a menu or toolbar needs
     -     to be updated. Return true if the command can be executed at the
     -     current time, false otherwise.
     - * doCommand(aTab, aCommand): Called when a menu or toolbar command is to
     -     be executed. Perform the action appropriate to the command.
     - * onEvent(aTab, aEvent): This can be used to handle different events on
     -     the window.
+    - * getBrowser(aTab): This function should return the browser element for
+    -     your tab if there is one (return null or don't define this function
+    -     otherwise). It is used for some toolkit functions that require a
+    -     global "getBrowser" function, e.g. ZoomManager.
     -
     - Tab monitoring code is expected to be used for widgets on the screen
     -  outside of the tab box that need to update themselves as the active tab
     -  changes.  This is primarily intended to be used for the ThunderBar; if
     -  you are not the ThunderBar and this sounds appealing to you, please
     -  solicit discussion on your needs on the mozilla.dev.apps.thunderbird
     -  newsgroup.
     - Tab monitoring code (un)registers itself via (un)registerTabMonitor.
@@ -481,16 +485,32 @@
               this.panelContainer.removeChild(tab.panel);
               delete tab.panel;
             }
             if (numTabs == 1 && this.tabContainer.mAutoHide)
               this.tabContainer.collapsed = true;
           ]]>
         </body>
       </method>
+      <!-- getBrowserForSelectedTab is required as some toolkit functions
+           require a getBrowser() function. -->
+      <method name="getBrowserForSelectedTab">
+        <body><![CDATA[
+          if (!this.currentTabInfo)
+            this.currentTabInfo = this.tabInfo[0];
+
+          let tab = this.currentTabInfo;
+
+          let browserFunc = tab.mode.getBrowser || tab.mode.tabType.getBrowser;
+          if (browserFunc)
+            return browserFunc.call(tab.mode.tabType, tab);
+
+          return null;
+        ]]></body>
+      </method>
       <method name="removeCurrentTab">
         <body><![CDATA[
           this.removeTabByNode(
             this.tabContainer.childNodes[this.tabContainer.selectedIndex]);
         ]]></body>
       </method>
       <!--  UpdateCurrentTab - called in response to changing the current tab -->
       <method name="updateCurrentTab">