Bug 580638 - App Tab closes with keystroke or middle click. r=dao. a=blocker.
authorAsaf Romano (Mano) <mano@mozilla.com>
Mon, 07 Feb 2011 15:54:26 +0200
changeset 62092 88952ceddd0552e04e594aca15c57b6bb44ed525
parent 62091 e1fea09f31bf57ccdc9dbf4c259af74acfd8972b
child 62093 bf732d3308db9998c25d60e1ad509d45a788af7e
push id1
push userroot
push dateTue, 10 Dec 2013 15:46:25 +0000
reviewersdao, blocker
bugs580638
milestone2.0b12pre
Bug 580638 - App Tab closes with keystroke or middle click. r=dao. a=blocker.
browser/base/content/tabbrowser.xml
browser/base/content/test/Makefile.in
browser/base/content/test/browser_bug580638.js
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -185,32 +185,71 @@
           var show = document.getElementById("addon-bar").collapsed &&
                      window.windowState == window.STATE_NORMAL;
           for (let i = 0; i < this.browsers.length; i++) {
             this.browsers[i].showWindowResizer = show;
           }
         ]]></body>
       </method>
 
+      <method name="_setCloseKeyState">
+        <parameter name="aEnabled"/>
+        <body><![CDATA[
+          let keyClose = document.getElementById("key_close");
+          let closeKeyEnabled = keyClose.getAttribute("disabled") != "true";
+          if (closeKeyEnabled == aEnabled)
+            return;
+
+          if (aEnabled)
+            keyClose.removeAttribute("disabled");
+          else
+            keyClose.setAttribute("disabled", "true");
+
+          // We also want to remove the keyboard shortcut from the file menu
+          // when the shortcut is disabled, and bring it back when it's
+          // renabled.
+          //
+          // Fixing bug 630826 could make that happen automatically.
+          // Fixing bug 630830 could avoid the ugly hack below.
+          
+          let closeMenuItem = document.getElementById("menu_close");
+          let parentPopup = closeMenuItem.parentNode;
+          let nextItem = closeMenuItem.nextSibling;
+          let clonedItem = closeMenuItem.cloneNode(true);
+
+          parentPopup.removeChild(closeMenuItem);
+
+          if (aEnabled)
+            clonedItem.setAttribute("key", "key_close");
+          else
+            clonedItem.removeAttribute("key");
+
+          parentPopup.insertBefore(clonedItem, nextItem);
+        ]]></body>
+      </method>
+
       <method name="pinTab">
         <parameter name="aTab"/>
         <body><![CDATA[
           if (aTab.pinned)
             return;
 
           if (aTab.hidden)
             this.showTab(aTab);
 
           this.moveTabTo(aTab, this._numPinnedTabs);
           aTab.setAttribute("pinned", "true");
           this.tabContainer._positionPinnedTabs();
           this.tabContainer.adjustTabstrip();
 
           this.getBrowserForTab(aTab).docShell.isAppTab = true;
 
+          if (aTab.selected)
+            this._setCloseKeyState(false);
+
           let event = document.createEvent("Events");
           event.initEvent("TabPinned", true, false);
           aTab.dispatchEvent(event);
         ]]></body>
       </method>
 
       <method name="unpinTab">
         <parameter name="aTab"/>
@@ -222,16 +261,19 @@
           aTab.setAttribute("fadein", "true");
           aTab.removeAttribute("pinned");
           aTab.style.MozMarginStart = "";
           this.tabContainer._positionPinnedTabs();
           this.tabContainer.adjustTabstrip();
 
           this.getBrowserForTab(aTab).docShell.isAppTab = false;
 
+          if (aTab.selected)
+            this._setCloseKeyState(true);
+
           let event = document.createEvent("Events");
           event.initEvent("TabUnpinned", true, false);
           aTab.dispatchEvent(event);
         ]]></body>
       </method>
 
       <method name="previewTab">
         <parameter name="aTab"/>
@@ -887,16 +929,19 @@
               this.mIsBusy = false;
               this._callProgressListeners(null, "onStateChange",
                                           [webProgress, null,
                                            nsIWebProgressListener.STATE_STOP |
                                            nsIWebProgressListener.STATE_IS_NETWORK, 0],
                                           true, false);
             }
 
+            if (this.mCurrentTab.selected)
+              this._setCloseKeyState(!this.mCurrentTab.pinned);
+
             // TabSelect events are suppressed during preview mode to avoid confusing extensions and other bits of code
             // that might rely upon the other changes suppressed.
             // Focus is suppressed in the event that the main browser window is minimized - focusing a tab would restore the window
             if (!this._previewMode) {
               // We've selected the new tab, so go ahead and notify listeners.
               let event = document.createEvent("Events");
               event.initEvent("TabSelect", true, false);
               this.mCurrentTab.dispatchEvent(event);
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -145,16 +145,17 @@ endif
                  browser_bug561636.js \
                  browser_bug562649.js \
                  browser_bug563588.js \
                  browser_bug565575.js \
                  browser_zbug569342.js \
                  browser_bug575561.js \
                  browser_bug577121.js \
                  browser_bug579872.js \
+                 browser_bug580638.js \
                  browser_bug580956.js \
                  browser_bug581242.js \
                  browser_bug581253.js \
                  browser_bug581947.js \
                  browser_bug585785.js \
                  browser_bug585830.js \
                  browser_bug590206.js \
                  browser_bug592338.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug580638.js
@@ -0,0 +1,91 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is bug 597218 test.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Asaf Romano <mano@mozill.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function test() {
+  waitForExplicitFinish();
+
+  function testState(aPinned) {
+    function elemAttr(id, attr) document.getElementById(id).getAttribute(attr);
+
+    if (aPinned) {
+      is(elemAttr("key_close", "disabled"), "true",
+         "key_close should be disabled when a pinned-tab is selected");
+      is(elemAttr("menu_close", "key"), "",
+         "menu_close shouldn't have a key set when a pinned is selected");
+    }
+    else {
+      is(elemAttr("key_close", "disabled"), "",
+         "key_closed shouldn't have disabled state set when a non-pinned tab is selected");
+      is(elemAttr("menu_close", "key"), "key_close",
+         "menu_close should have key_close set as its key when a non-pinned tab is selected");
+    }
+  }
+
+  let lastSelectedTab = gBrowser.selectedTab;
+  ok(!lastSelectedTab.pinned, "We should have started with a regular tab selected");
+
+  testState(false);
+
+  let pinnedTab = gBrowser.addTab("about:blank");
+  gBrowser.pinTab(pinnedTab);
+
+  // Just pinning the tab shouldn't change the key state.
+  testState(false);
+
+  // Test updating key state after selecting a tab.
+  gBrowser.selectedTab = pinnedTab;
+  testState(true);
+
+  gBrowser.selectedTab = lastSelectedTab;
+  testState(false);
+  
+  gBrowser.selectedTab = pinnedTab;
+  testState(true);
+
+  // Test updating the key state after un/pinning the tab.
+  gBrowser.unpinTab(pinnedTab);
+  testState(false);
+
+  gBrowser.pinTab(pinnedTab);  
+  testState(true);
+
+  // Test updating the key state after removing the tab.
+  gBrowser.removeTab(pinnedTab);
+  testState(false);
+
+  finish();
+}