Bug 436304 - Implement All Tabs panel with previews and search. r=connor
authorDão Gottwald <dao@mozilla.com>
Wed, 05 Nov 2008 08:38:13 +0100
changeset 21338 bf2f8ad8f1ce19a0c40007da760ec267089061c3
parent 21337 a6e0b26a65e89e43dfbe844d34b7bbef387ded71
child 21339 dcec193ba5d7e5e863e58f8ba3a813930fa7c873
push idunknown
push userunknown
push dateunknown
reviewersconnor
bugs436304
milestone1.9.1b2pre
Bug 436304 - Implement All Tabs panel with previews and search. r=connor
browser/app/profile/firefox.js
browser/base/content/browser-tabPreviews.js
browser/base/content/browser-tabPreviews.xml
browser/base/content/browser.css
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/tabbrowser.css
browser/base/content/tabbrowser.xml
browser/base/content/test/browser_ctrlTab.js
browser/base/jar.mn
browser/locales/en-US/chrome/browser/browser.dtd
browser/themes/gnomestripe/browser/browser.css
browser/themes/gnomestripe/browser/jar.mn
browser/themes/gnomestripe/browser/tabbrowser/alltabs.png
browser/themes/pinstripe/browser/browser.css
browser/themes/winstripe/browser/browser-aero.css
browser/themes/winstripe/browser/browser.css
browser/themes/winstripe/browser/jar.mn
browser/themes/winstripe/browser/tabbrowser/alltabs-box-overflow-end-bkgnd-hover.png
browser/themes/winstripe/browser/tabbrowser/alltabs-box-overflow-end-bkgnd.png
browser/themes/winstripe/browser/tabbrowser/alltabs-box-overflow-start-bkgnd-hover.png
browser/themes/winstripe/browser/tabbrowser/alltabs-box-overflow-start-bkgnd.png
browser/themes/winstripe/browser/tabbrowser/alltabs.png
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -334,17 +334,17 @@ pref("browser.tabs.closeButtons", 1);
 
 // When tabs opened by links in other tabs via a combination of 
 // browser.link.open_newwindow being set to 3 and target="_blank" etc are
 // closed:
 // true   return to the tab that opened this tab (its owner)
 // false  return to the adjacent tab (old default)
 pref("browser.tabs.selectOwnerOnClose", true);
 
-pref("browser.ctrlTab.mostRecentlyUsed", true);
+pref("browser.ctrlTab.previews", true);
 pref("browser.ctrlTab.recentlyUsedLimit", 7);
 
 // Default bookmark sorting
 pref("browser.bookmarks.sort.direction", "descending");
 pref("browser.bookmarks.sort.resource", "rdf:http://home.netscape.com/NC-rdf#Name");
 
 // By default, do not export HTML at shutdown.
 // If true, at shutdown the bookmarks in your menu and toolbar will
--- a/browser/base/content/browser-tabPreviews.js
+++ b/browser/base/content/browser-tabPreviews.js
@@ -38,37 +38,37 @@
 #endif
  */
 
 /**
  * Tab previews utility, produces thumbnails
  */
 var tabPreviews = {
   aspectRatio: 0.5625, // 16:9
-  init: function () {
+  init: function tabPreviews__init() {
     this.width = Math.ceil(screen.availWidth / 5);
     this.height = Math.round(this.width * this.aspectRatio);
 
     gBrowser.tabContainer.addEventListener("TabSelect", this, false);
     gBrowser.tabContainer.addEventListener("SSTabRestored", this, false);
   },
-  uninit: function () {
+  uninit: function tabPreviews__uninit() {
     gBrowser.tabContainer.removeEventListener("TabSelect", this, false);
     gBrowser.tabContainer.removeEventListener("SSTabRestored", this, false);
     this._selectedTab = null;
   },
-  get: function (aTab) {
+  get: function tabPreviews__get(aTab) {
     if (aTab.__thumbnail_lastURI &&
         aTab.__thumbnail_lastURI != aTab.linkedBrowser.currentURI.spec) {
       aTab.__thumbnail = null;
       aTab.__thumbnail_lastURI = null;
     }
     return aTab.__thumbnail || this.capture(aTab, !aTab.hasAttribute("busy"));
   },
-  capture: function (aTab, aStore) {
+  capture: function tabPreviews__capture(aTab, aStore) {
     var thumbnail = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
     thumbnail.mozOpaque = true;
     thumbnail.height = this.height;
     thumbnail.width = this.width;
 
     var ctx = thumbnail.getContext("2d");
     var win = aTab.linkedBrowser.contentWindow;
     var snippetWidth = win.innerWidth * .6;
@@ -78,17 +78,17 @@ var tabPreviews = {
                    snippetWidth, snippetWidth * this.aspectRatio, "rgb(255,255,255)");
 
     if (aStore) {
       aTab.__thumbnail = thumbnail;
       aTab.__thumbnail_lastURI = aTab.linkedBrowser.currentURI.spec;
     }
     return thumbnail;
   },
-  handleEvent: function (event) {
+  handleEvent: function tabPreviews__handleEvent(event) {
     switch (event.type) {
       case "TabSelect":
         if (this._selectedTab &&
             this._selectedTab.parentNode &&
             !this._pendingUpdate) {
           // Generate a thumbnail for the tab that was selected.
           // The timeout keeps the UI snappy and prevents us from generating thumbnails
           // for tabs that will be closed. During that timeout, don't generate other
@@ -112,19 +112,19 @@ var tabPreviews = {
 /**
  * Ctrl-Tab panel
  */
 var ctrlTab = {
   get panel () {
     delete this.panel;
     return this.panel = document.getElementById("ctrlTab-panel");
   },
-  get label () {
-    delete this.label;
-    return this.label = document.getElementById("ctrlTab-label");
+  get searchField () {
+    delete this.searchField;
+    return this.searchField = document.getElementById("ctrlTab-search");
   },
   get pagesBar () {
     delete this.pagesBar;
     return this.pagesBar = document.getElementById("ctrlTab-pages");
   },
   get thumbnails () {
     delete this.thumbnails;
     return this.thumbnails = this.panel.getElementsByClassName("ctrlTab-thumbnail");
@@ -133,257 +133,336 @@ var ctrlTab = {
     delete this.columns;
     return this.columns = this.thumbnails.length /
                           this.panel.getElementsByClassName("ctrlTab-row").length;
   },
   get closeCharCode () {
     delete this.closeCharCode;
     return this.closeCharCode = document.getElementById("key_close")
                                         .getAttribute("key")
-                                        .toLowerCase().charCodeAt(0);
+                                        .toLocaleLowerCase().charCodeAt(0);
+  },
+  get findCharCode () {
+    delete this.findCharCode;
+    return this.findCharCode = document.getElementById("key_find")
+                                       .getAttribute("key")
+                                       .toLocaleLowerCase().charCodeAt(0);
   },
   get recentlyUsedLimit () {
     delete this.recentlyUsedLimit;
     return this.recentlyUsedLimit = gPrefService.getIntPref("browser.ctrlTab.recentlyUsedLimit");
   },
   selectedIndex: 0,
   get selected () this.thumbnails.item(this.selectedIndex),
   get isOpen   () this.panel.state == "open" || this.panel.state == "showing",
-  get tabCount () gBrowser.mTabs.length - (this._closing ? 1 : 0),
-  get pages    () Math.ceil(this.tabCount / this.thumbnails.length),
-  get page     () this._page || 0,
-  set page (page) {
+  get tabCount () this.tabList.length,
+
+  get sticky () this.panel.hasAttribute("sticky"),
+  set sticky (val) {
+    if (val)
+      this.panel.setAttribute("sticky", "true");
+    else
+      this.panel.removeAttribute("sticky");
+    return val;
+  },
+
+  get pages () Math.ceil(this.tabCount / this.thumbnails.length),
+  get page  () this._page || 0,
+  set page  (page) {
     if (page < 0)
       page = this.pages - 1;
     else if (page >= this.pages)
       page = 0;
 
     if (this.pagesBar.childNodes.length) {
       this.pagesBar.childNodes[this.page].removeAttribute("selected");
       this.pagesBar.childNodes[page].setAttribute("selected", "true");
     }
 
     this._page = page;
     this.updatePreviews();
     return page;
   },
+
   get tabList () {
+    if (this._tabList)
+      return this._tabList;
+
     var list = Array.slice(gBrowser.mTabs);
+
     if (this._closing)
       this.detachTab(this._closing, list);
+
     for (let i = 0; i < gBrowser.tabContainer.selectedIndex; i++)
       list.push(list.shift());
+
     if (!this._useTabBarOrder && this.recentlyUsedLimit != 0) {
       let recentlyUsedTabs = this._recentlyUsedTabs;
       if (this.recentlyUsedLimit > 0)
         recentlyUsedTabs = this._recentlyUsedTabs.slice(0, this.recentlyUsedLimit);
       for (let i = recentlyUsedTabs.length - 1; i >= 0; i--) {
         list.splice(list.indexOf(recentlyUsedTabs[i]), 1);
         list.unshift(recentlyUsedTabs[i]);
       }
     }
-    return list;
+
+    if (this.searchField.value) {
+      list = list.filter(function (tab) {
+        let lowerCaseLabel, uri;
+        for (let i = 0; i < this.length; i++) {
+          if (tab.label.indexOf(this[i]) != -1)
+            continue;
+
+          if (!lowerCaseLabel)
+            lowerCaseLabel = tab.label.toLocaleLowerCase();
+          if (lowerCaseLabel.indexOf(this[i]) != -1)
+            continue;
+
+          if (!uri) {
+            uri = tab.linkedBrowser.currentURI.spec;
+            try {
+              uri = decodeURI(uri);
+            } catch (e) {}
+          }
+          if (uri.indexOf(this[i]) != -1)
+            continue;
+
+          return false;
+        }
+        return true;
+      }, this.searchField.value.split(/\s+/g));
+    }
+
+    return this._tabList = list;
   },
-  init: function () {
+
+  init: function ctrlTab__init() {
     if (this._recentlyUsedTabs)
       return;
     this._recentlyUsedTabs = [gBrowser.selectedTab];
 
     var tabContainer = gBrowser.tabContainer;
     tabContainer.addEventListener("TabOpen", this, false);
     tabContainer.addEventListener("TabSelect", this, false);
     tabContainer.addEventListener("TabClose", this, false);
 
-    gBrowser.mTabBox.handleCtrlTab = false;
+    this._handleCtrlTab =
+      gPrefService.getBoolPref("browser.ctrlTab.previews") &&
+      (!gPrefService.prefHasUserValue("browser.ctrlTab.disallowForScreenReaders") ||
+       !gPrefService.getBoolPref("browser.ctrlTab.disallowForScreenReaders"));
+    if (this._handleCtrlTab)
+      gBrowser.mTabBox.handleCtrlTab = false;
     document.addEventListener("keypress", this, false);
   },
-  uninit: function () {
+
+  uninit: function ctrlTab__uninit() {
     this._recentlyUsedTabs = null;
 
     var tabContainer = gBrowser.tabContainer;
     tabContainer.removeEventListener("TabOpen", this, false);
     tabContainer.removeEventListener("TabSelect", this, false);
     tabContainer.removeEventListener("TabClose", this, false);
 
     this.panel.removeEventListener("popuphiding", this, false);
+    this.panel.removeEventListener("popupshown", this, false);
+    this.panel.removeEventListener("popuphidden", this, false);
     document.removeEventListener("keypress", this, false);
-    gBrowser.mTabBox.handleCtrlTab = true;
+    if (this._handleCtrlTab)
+      gBrowser.mTabBox.handleCtrlTab = true;
   },
-  buildPagesBar: function () {
+
+  search: function ctrlTab__search() {
+    if (this.isOpen) {
+      this._tabList = null;
+      this.buildPagesBar();
+      this.goToPage(0, 0);
+      this.updatePreviews();
+    }
+  },
+
+  buildPagesBar: function ctrlTab__buildPagesBar() {
     var pages = this.pages;
     if (pages == 1)
       pages = 0;
     while (this.pagesBar.childNodes.length > pages)
       this.pagesBar.removeChild(this.pagesBar.lastChild);
     while (this.pagesBar.childNodes.length < pages) {
       let pointer = document.createElement("spacer");
       pointer.setAttribute("onclick", "ctrlTab.goToPage(" + this.pagesBar.childNodes.length + ");");
       pointer.setAttribute("class", "ctrlTab-pagePointer");
       this.pagesBar.appendChild(pointer);
     }
   },
-  goToPage: function (aPage, aIndex) {
-    if (this.page != aPage)
-      this.page = aPage;
+
+  goToPage: function ctrlTab__goToPage(aPage, aIndex) {
+    this.page = aPage;
     this.selected.removeAttribute("selected");
     if (aIndex) {
       this.selectedIndex = aIndex;
       while (!this.selected || !this.selected.hasAttribute("valid"))
         this.selectedIndex--;
     } else {
       this.selectedIndex = 0;
     }
     this.updateSelected();
   },
-  updatePreviews: function () {
+
+  updatePreviews: function ctrlTab__updatePreviews() {
     var tabs = this.tabList;
     var offset = this.page * this.thumbnails.length;
     for (let i = 0; i < this.thumbnails.length; i++)
       this.updatePreview(this.thumbnails[i], tabs[i + offset]);
   },
-  updatePreview: function (aThumbnail, aTab) {
+  updatePreview: function ctrlTab__updatePreview(aThumbnail, aTab) {
     do {
       if (aThumbnail._tab) {
         if (aThumbnail._tab == aTab)
           break;
         aThumbnail._tab.removeEventListener("DOMAttrModified", this, false);
       }
       aThumbnail._tab = aTab;
       if (aTab)
         aTab.addEventListener("DOMAttrModified", this, false);
     } while (false);
 
     if (aThumbnail.firstChild)
       aThumbnail.removeChild(aThumbnail.firstChild);
     if (aTab) {
       aThumbnail.appendChild(tabPreviews.get(aTab));
       aThumbnail.setAttribute("valid", "true");
+      aThumbnail.setAttribute("label", aTab.label);
+      aThumbnail.setAttribute("crop", aTab.crop);
     } else {
+      let placeholder = document.createElement("hbox");
+      placeholder.height = tabPreviews.height;
+      aThumbnail.appendChild(placeholder);
       aThumbnail.removeAttribute("valid");
+      aThumbnail.setAttribute("label", "placeholder");
     }
     aThumbnail.width = tabPreviews.width;
-    aThumbnail.height = tabPreviews.height;
   },
-  tabAttrModified: function (aTab, aAttrName) {
+
+  tabAttrModified: function ctrlTab__tabAttrModified(aTab, aAttrName) {
     switch (aAttrName) {
+      case "label":
+      case "crop":
       case "busy":
         for (let i = this.thumbnails.length - 1; i >= 0; i--) {
           if (this.thumbnails[i]._tab == aTab) {
             this.updatePreview(this.thumbnails[i], aTab);
             break;
           }
         }
         break;
-      case "label":
-      case "crop":
-        if (this.selected._tab == aTab)
-          this.label[aAttrName == "label" ? "value" : aAttrName] = aTab[aAttrName];
-        break;
     }
   },
-  advanceSelected: function () {
+
+  advanceSelected: function ctrlTab__advanceSelected() {
     this.selected.removeAttribute("selected");
 
     this.selectedIndex += this.invertDirection ? -1 : 1;
     if (this.selectedIndex < 0) {
       this.page--;
       this.selectedIndex = this.thumbnails.length - 1;
       while (!this.selected.hasAttribute("valid"))
         this.selectedIndex--;
     } else if (this.selectedIndex >= this.thumbnails.length || !this.selected.hasAttribute("valid")) {
       this.page++;
       this.selectedIndex = 0;
     }
     this.updateSelected();
   },
-  updateSelected: function () {
-    var thumbnail = this.selected;
-    thumbnail.setAttribute("selected", "true");
-    this.label.value = thumbnail._tab.label;
-    this.label.crop = thumbnail._tab.crop;
-    var url = thumbnail._tab.linkedBrowser.currentURI.spec;
-    if (url == "about:blank") {
-      // XXXhack: Passing a space here (and not "")
-      // to make sure the browser implementation would
-      // still consider it a hovered link.
-      url = " ";
-    } else {
-      try {
-        url = decodeURI(url);
-      } catch (e) {}
-    }
-    XULBrowserWindow.setOverLink(url, null);
+
+  updateSelected: function ctrlTab__updateSelected() {
+    if (this.tabCount)
+      this.selected.setAttribute("selected", "true");
   },
-  thumbnailClick: function (event) {
-    switch (event.button) {
-      case 0:
-        this.selectThumbnail(event.currentTarget);
-        break;
-      case 1:
-        gBrowser.removeTab(event.currentTarget._tab);
-        break;
+
+  selectThumbnail: function ctrlTab__selectThumbnail(aThumbnail) {
+    if (this.tabCount) {
+      this._tabToSelect = (aThumbnail || this.selected)._tab;
+      this.panel.hidePopup();
     }
   },
-  selectThumbnail: function (aThumbnail) {
-    var selectedTab = (aThumbnail || this.selected)._tab;
-    this.panel.hidePopup();
-    gBrowser.selectedTab = selectedTab;
-  },
-  attachTab: function (aTab, aPos) {
+
+  attachTab: function ctrlTab__attachTab(aTab, aPos) {
     if (aPos == 0)
       this._recentlyUsedTabs.unshift(aTab);
     else if (aPos)
       this._recentlyUsedTabs.splice(aPos, 0, aTab);
     else
       this._recentlyUsedTabs.push(aTab);
   },
-  detachTab: function (aTab, aTabs) {
+  detachTab: function ctrlTab__detachTab(aTab, aTabs) {
     var tabs = aTabs || this._recentlyUsedTabs;
     var i = tabs.indexOf(aTab);
     if (i >= 0)
       tabs.splice(i, 1);
   },
-  open: function () {
-    if (window.allTabs)
-      allTabs.close();
+
+  open: function ctrlTab__open(aSticky) {
+    if (this.isOpen && this.sticky) {
+      this.panel.hidePopup();
+      return;
+    }
+    this.sticky = !!aSticky;
 
     this._deferOnTabSelect = [];
     if (this.invertDirection)
       this._useTabBarOrder = true;
 
     this._tabBarHandlesCtrlPageUpDown = gBrowser.mTabBox.handleCtrlPageUpDown;
     gBrowser.mTabBox.handleCtrlPageUpDown = false;
 
-    document.addEventListener("keyup", this, false);
-    document.addEventListener("keydown", this, false);
+    document.addEventListener("keyup", this, true);
+    document.addEventListener("keydown", this, true);
+    this.panel.addEventListener("popupshown", this, false);
     this.panel.addEventListener("popuphiding", this, false);
+    this.panel.addEventListener("popuphidden", this, false);
+    this._prevFocus = document.commandDispatcher.focusedElement ||
+                      document.commandDispatcher.focusedWindow;
     this.panel.hidden = false;
-    this.panel.width = screen.availWidth * .9;
+    this.panel.width = screen.availWidth * .85;
+    this.panel.popupBoxObject.setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
     this.panel.openPopupAtScreen(screen.availLeft + (screen.availWidth - this.panel.width) / 2,
-                                 screen.availTop + screen.availHeight * .1,
+                                 screen.availTop + screen.availHeight * .12,
                                  false);
     this.buildPagesBar();
     this.selectedIndex = 0;
     this.page = 0;
     this.advanceSelected();
   },
-  onKeyPress: function (event) {
+
+  onKeyPress: function ctrlTab__onKeyPress(event) {
     var isOpen = this.isOpen;
-    var propagate = !isOpen;
+
+    if (isOpen && event.target == this.searchField)
+      return;
+
+    if (isOpen) {
+      event.preventDefault();
+      event.stopPropagation();
+    }
+
     switch (event.keyCode) {
       case event.DOM_VK_TAB:
-        if (event.ctrlKey && !event.altKey && !event.metaKey) {
-          propagate = false;
+        if ((event.ctrlKey || this.sticky) && !event.altKey && !event.metaKey) {
           this.invertDirection = event.shiftKey;
-          if (isOpen)
+          if (isOpen) {
             this.advanceSelected();
-          else if (this.tabCount == 2)
-            gBrowser.selectedTab = this.tabList[1];
-          else if (this.tabCount > 2)
-            this.open();
+          } else if (this._handleCtrlTab) {
+            event.preventDefault();
+            event.stopPropagation();
+            if (gBrowser.mTabs.length > 2) {
+              this.open();
+            } else if (gBrowser.mTabs.length == 2) {
+              gBrowser.selectedTab = gBrowser.selectedTab.nextSibling ||
+                                     gBrowser.selectedTab.previousSibling;
+            }
+          }
         }
         break;
       case event.DOM_VK_UP:
         if (isOpen) {
           let index = this.selectedIndex - this.columns;
           if (index < 0) {
             this.goToPage(this.page - 1, this.thumbnails.length + index);
           } else {
@@ -430,72 +509,92 @@ var ctrlTab = {
       case event.DOM_VK_PAGE_UP:
         if (isOpen)
           this.goToPage(this.page - 1);
         break;
       case event.DOM_VK_PAGE_DOWN:
         if (isOpen)
           this.goToPage(this.page + 1);
         break;
+      case event.DOM_VK_RETURN:
+        if (isOpen && this.sticky)
+          this.selectThumbnail();
+        break;
       case event.DOM_VK_ESCAPE:
         if (isOpen)
           this.panel.hidePopup();
         break;
       default:
-        if (isOpen && event.charCode == this.closeCharCode)
-          gBrowser.removeTab(this.selected._tab);
-    }
-    if (!propagate) {
-      event.stopPropagation();
-      event.preventDefault();
+        if (isOpen && event.ctrlKey) {
+          switch (event.charCode) {
+            case this.closeCharCode:
+              gBrowser.removeTab(this.selected._tab);
+              break;
+            case this.findCharCode:
+              this.searchField.focus();
+              break;
+          }
+        }
     }
   },
-  onPopupHiding: function () {
+  onPopupHiding: function ctrlTab__onPopupHiding() {
     gBrowser.mTabBox.handleCtrlPageUpDown = this._tabBarHandlesCtrlPageUpDown;
-    document.removeEventListener("keyup", this, false);
-    document.removeEventListener("keydown", this, false);
+    document.removeEventListener("keyup", this, true);
+    document.removeEventListener("keydown", this, true);
 
     this.selected.removeAttribute("selected");
     if (this.pagesBar.childNodes.length)
       this.pagesBar.childNodes[this.page].removeAttribute("selected");
 
     Array.forEach(this.thumbnails, function (thumbnail) {
       this.updatePreview(thumbnail, null);
     }, this);
 
+    this.searchField.value = "";
     this.invertDirection = false;
+    this.sticky = false;
     this._useTabBarOrder = false;
-    this.label.value = "";
-    XULBrowserWindow.setOverLink("", null);
     this._page = null;
+    this._tabList = null;
 
     this._deferOnTabSelect.forEach(this.onTabSelect, this);
     this._deferOnTabSelect = null;
+
+    this._prevFocus.focus();
+    this._prevFocus = null;
+
+    if (this._tabToSelect) {
+      gBrowser.selectedTab = this._tabToSelect;
+      this._tabToSelect = null;
+    }
   },
-  onTabSelect: function (aTab) {
+  onTabSelect: function ctrlTab__onTabSelect(aTab) {
     if (aTab.parentNode) {
       this.detachTab(aTab);
       this.attachTab(aTab, 0);
     }
   },
-  removeClosingTabFromUI: function (aTab) {
+
+  removeClosingTabFromUI: function ctrlTab__removeClosingTabFromUI(aTab) {
     this._closing = aTab;
+    this._tabList = null;
     if (this.tabCount == 1) {
       this.panel.hidePopup();
     } else {
       this.buildPagesBar();
       this.updatePreviews();
       if (!this.selected.hasAttribute("valid"))
         this.advanceSelected();
       else
         this.updateSelected();
     }
     this._closing = null;
   },
-  handleEvent: function (event) {
+
+  handleEvent: function ctrlTab__handleEvent(event) {
     switch (event.type) {
       case "DOMAttrModified":
         this.tabAttrModified(event.target, event.attrName);
         break;
       case "TabSelect":
         if (this.isOpen)
           // don't change the tab order while the panel is open
           this._deferOnTabSelect.push(event.target);
@@ -510,20 +609,39 @@ var ctrlTab = {
         if (this.isOpen)
           this.removeClosingTabFromUI(event.target);
         break;
       case "keypress":
         this.onKeyPress(event);
         break;
       case "keydown":
       case "keyup":
-        // the panel is open; don't propagate any key events
-        event.stopPropagation();
-        event.preventDefault();
-        if (event.type == "keyup" && event.keyCode == event.DOM_VK_CONTROL)
+        if (event.target == this.searchField) {
+          if (event.keyCode == event.DOM_VK_RETURN ||
+              event.keyCode == event.DOM_VK_ESCAPE)
+            this.panel.focus();
+        } else {
+          // Manually consume the events, as the panel is open but doesn't
+          // necessarily have focus.
+          event.stopPropagation();
+          event.preventDefault();
+        }
+
+        if (!this.sticky &&
+            event.type == "keyup" &&
+            event.keyCode == event.DOM_VK_CONTROL)
           this.selectThumbnail();
         break;
+      case "popupshown":
+        if (this.sticky)
+          this.searchField.focus();
+        break;
       case "popuphiding":
         this.onPopupHiding();
         break;
+      case "popuphidden":
+        // Destroy the widget in order to prevent outdated content
+        // when re-opening the panel.
+        this.panel.hidden = true;
+        break;
     }
   }
 };
new file mode 100644
--- /dev/null
+++ b/browser/base/content/browser-tabPreviews.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+
+# -*- Mode: HTML -*-
+# ***** 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 mozilla.org browser.
+#
+# The Initial Developer of the Original Code is Mozilla.
+# Portions created by the Initial Developer are Copyright (C) 2006
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Dão Gottwald <dao@mozilla.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 *****
+
+<bindings id="tabPreviews"
+          xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          xmlns:xbl="http://www.mozilla.org/xbl">
+  <binding id="ctrlTab-thumbnail">
+    <content align="center">
+      <children/>
+      <xul:label xbl:inherits="value=label,crop"/>
+    </content>
+    <handlers>
+      <handler event="click" button="0" action="ctrlTab.selectThumbnail(this);"/>
+      <handler event="click" button="1" action="gBrowser.removeTab(this._tab);"/>
+    </handlers>
+  </binding>
+</bindings>
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -93,11 +93,24 @@ window[chromehidden~="toolbar"] toolbar:
   height: 5px;
 }
 
 #navigator-toolbox[inFullscreen="true"] #fullscr-toggler {
   display: -moz-box;
 }
 
 /* Tab Previews */
+.ctrlTab-thumbnail {
+  -moz-binding: url("chrome://browser/content/browser-tabPreviews.xml#ctrlTab-thumbnail");
+}
+
 .ctrlTab-thumbnail:not([valid]) {
   visibility: hidden;
 }
+
+#ctrlTab-pages {
+  display: block;
+  text-align: center;
+}
+ 
+.ctrlTab-pagePointer {
+  display: inline-block;
+}
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1255,20 +1255,17 @@ function delayedStartup(isLoadingBlank, 
 
   // Attach a listener to watch for "command" events bubbling up from error
   // pages.  This lets us fix bugs like 401575 which require error page UI to
   // do privileged things, without letting error pages have any privilege
   // themselves.
   gBrowser.addEventListener("command", BrowserOnCommand, false);
 
   tabPreviews.init();
-  if ((!gPrefService.prefHasUserValue("browser.ctrlTab.disallowForScreenReaders") ||
-       !gPrefService.getBoolPref("browser.ctrlTab.disallowForScreenReaders")) &&
-       gPrefService.getBoolPref("browser.ctrlTab.mostRecentlyUsed"))
-    ctrlTab.init();
+  ctrlTab.init();
 
   // Initialize the microsummary service by retrieving it, prompting its factory
   // to create its singleton, whose constructor initializes the service.
   // Started 4 seconds after delayedStartup (before the livemarks service below).
   setTimeout(function() {
     try {
       Cc["@mozilla.org/microsummary/service;1"].getService(Ci.nsIMicrosummaryService);
     } catch (ex) {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -228,37 +228,43 @@
         </vbox>
       </hbox>
     </panel>
 
     <tooltip id="urlTooltip">
       <label crop="center" flex="1" class="tooltip-label"/>
     </tooltip>
 
-    <panel id="ctrlTab-panel" class="KUI-panel" hidden="true" noautofocus="true" level="top"
+    <panel id="ctrlTab-panel" class="KUI-panel" hidden="true" norestorefocus="true"
 #ifdef XP_WIN
 # XXX bug 457997
       noautohide="true"
 #endif
     >
-      <label id="ctrlTab-label" flex="1"/>
-      <hbox class="ctrlTab-row">
-        <hbox flex="1" pack="center"><hbox class="ctrlTab-thumbnail" onclick="ctrlTab.thumbnailClick(event);"/></hbox>
-        <hbox class="ctrlTab-thumbnail" onclick="ctrlTab.thumbnailClick(event);"/>
-        <hbox flex="1" pack="center"><hbox class="ctrlTab-thumbnail" onclick="ctrlTab.thumbnailClick(event);"/></hbox>
+      <hbox pack="center">
+        <textbox id="ctrlTab-search"
+                 type="search"
+                 emptytext="&ctrlTab.search.emptyText;"
+                 oncommand="ctrlTab.search();"
+                 onfocus="ctrlTab.sticky = true;"/>
       </hbox>
       <hbox class="ctrlTab-row">
-        <hbox flex="1" pack="center"><hbox class="ctrlTab-thumbnail" onclick="ctrlTab.thumbnailClick(event);"/></hbox>
-        <hbox class="ctrlTab-thumbnail" onclick="ctrlTab.thumbnailClick(event);"/>
-        <hbox flex="1" pack="center"><hbox class="ctrlTab-thumbnail" onclick="ctrlTab.thumbnailClick(event);"/></hbox>
+        <hbox flex="1" pack="center"><vbox class="ctrlTab-thumbnail"/></hbox>
+        <vbox class="ctrlTab-thumbnail"/>
+        <hbox flex="1" pack="center"><vbox class="ctrlTab-thumbnail"/></hbox>
       </hbox>
       <hbox class="ctrlTab-row">
-        <hbox flex="1" pack="center"><hbox class="ctrlTab-thumbnail" onclick="ctrlTab.thumbnailClick(event);"/></hbox>
-        <hbox class="ctrlTab-thumbnail" onclick="ctrlTab.thumbnailClick(event);"/>
-        <hbox flex="1" pack="center"><hbox class="ctrlTab-thumbnail" onclick="ctrlTab.thumbnailClick(event);"/></hbox>
+        <hbox flex="1" pack="center"><vbox class="ctrlTab-thumbnail"/></hbox>
+        <vbox class="ctrlTab-thumbnail"/>
+        <hbox flex="1" pack="center"><vbox class="ctrlTab-thumbnail"/></hbox>
+      </hbox>
+      <hbox class="ctrlTab-row">
+        <hbox flex="1" pack="center"><vbox class="ctrlTab-thumbnail"/></hbox>
+        <vbox class="ctrlTab-thumbnail"/>
+        <hbox flex="1" pack="center"><vbox class="ctrlTab-thumbnail"/></hbox>
       </hbox>
       <hbox id="ctrlTab-pages"/>
     </panel>
   </popupset>
 
   <!-- bookmarks toolbar tooltip -->
   <tooltip id="btTooltip" noautohide="true"
            onpopupshowing="return BookmarksEventHandler.fillInBTTooltip(document.tooltipNode)">
--- a/browser/base/content/tabbrowser.css
+++ b/browser/base/content/tabbrowser.css
@@ -7,20 +7,16 @@
 }
 
 %ifdef XP_MACOSX
 .tabbrowser-arrowscrollbox {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-arrowscrollbox");
 }
 %endif
 
-.tabs-alltabs-popup {
-  -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup");
-}
-
 .tab-close-button, .tabs-closebutton {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-close-tab-button");
 }
 
 .tab-close-button {
   display: none;
 }
 
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2731,23 +2731,20 @@
 #endif
                               class="tabbrowser-arrowscrollbox">
             <children/>
           </xul:arrowscrollbox>
           <xul:toolbarbutton class="tabs-newtab-button" anonid="newtab-button"
                              command="cmd_newNavigatorTab" chromedir="&locale.dir;"
                              tooltiptext="&newTabButton.tooltip;"/>
           <xul:stack align="center" pack="end" chromedir="&locale.dir;">
-            <xul:hbox flex="1" class="tabs-alltabs-box" anonid="alltabs-box"/>
             <xul:hbox flex="1" class="tabs-alltabs-box-animate" anonid="alltabs-box-animate"/>
-            <xul:toolbarbutton class="tabs-alltabs-button" type="menu" anonid="alltabs-button"
-                               tooltipstring="&listAllTabs.label;">
-              <xul:menupopup class="tabs-alltabs-popup" anonid="alltabs-popup"
-                             position="after_end"/>
-            </xul:toolbarbutton>
+            <xul:toolbarbutton class="tabs-alltabs-button" anonid="alltabs-button"
+                               tooltiptext="&listAllTabs.label;"
+                               oncommand="ctrlTab.open(true);"/>
           </xul:stack>
 #ifdef XP_MACOSX
           <xul:hbox anonid="tabstrip-closebutton" class="tabs-closebutton-box" align="center" pack="end" chromedir="&locale.dir;">
 #endif
           <xul:toolbarbutton anonid="tabs-closebutton"
                              class="close-button tabs-closebutton" chromedir="&locale.dir;"/>
 #ifdef XP_MACOSX
           </xul:hbox>
@@ -2930,38 +2927,28 @@
                 this._handleTabSelect();
                 this.mTabstripWidth = width;
               }
               break;
           }
         ]]></body>
       </method>
 
-      <field name="mAllTabsPopup">
-        document.getAnonymousElementByAttribute(this, 
-                                                "anonid", "alltabs-popup");
-      </field>
-
       <field name="mAllTabsBoxAnimate">
         document.getAnonymousElementByAttribute(this, 
                                                 "anonid",
                                                 "alltabs-box-animate");
       </field>
 
 #ifdef XP_MACOSX
       <field name="mDownBoxAnimate">
         this.mTabstrip._scrollButtonDownBoxAnimate;
       </field>
 #endif
 
-      <field name="mAllTabsButton">
-        document.getAnonymousElementByAttribute(this, 
-                                                "anonid", "alltabs-button");
-      </field>
-
       <field name="_animateTimer">null</field>
       <field name="_animateStep">-1</field>
       <field name="_animateDelay">25</field>
       <field name="_animatePercents">
        [1.00, 0.85, 0.80, 0.75, 0.71, 0.68, 0.65, 0.62, 0.59, 0.57,
         0.54, 0.52, 0.50, 0.47, 0.45, 0.44, 0.42, 0.40, 0.38, 0.37,
         0.35, 0.34, 0.32, 0.31, 0.30, 0.29, 0.28, 0.27, 0.26, 0.25,
         0.24, 0.23, 0.23, 0.22, 0.22, 0.21, 0.21, 0.21, 0.20, 0.20,
@@ -3044,236 +3031,16 @@
             this._animateStep++;
           else
             this._stopAnimation();
         ]]></body>
       </method>
     </implementation>
     <handlers>
       <handler event="TabSelect" action="this._handleTabSelect();"/>
-      <handler event="mouseover"><![CDATA[
-        if (event.originalTarget == this.mAllTabsButton) {
-          this.mAllTabsButton
-              .setAttribute("tooltiptext",
-                            this.mAllTabsButton.getAttribute("tooltipstring"));
-        }
-        else
-          this.mAllTabsButton.removeAttribute("tooltiptext");
-      ]]></handler>
-    </handlers>
-  </binding>
-
-  <!-- alltabs-popup binding
-       This binding relies on the structure of the tabbrowser binding.
-       Therefore it should only be used as a child of the tabs element.
-       This binding is exposed as a pseudo-public-API so themes can customize
-       the tabbar appearance without having to be scriptable
-       (see globalBindings.xml in Pinstripe for example).
-  -->
-  <binding id="tabbrowser-alltabs-popup"
-           extends="chrome://global/content/bindings/popup.xml#popup">
-    <implementation implements="nsIDOMEventListener">
-      <field name="_xulWindow">
-        null
-      </field>
-
-      <constructor><![CDATA[
-        // We cannot cache the XULBrowserWindow object itself since it might
-        // be set after this binding is constructed.
-        try {
-          this._xulWindow = 
-            window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                  .getInterface(Components.interfaces.nsIWebNavigation)
-                  .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
-                  .treeOwner
-                  .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                  .getInterface(Components.interfaces.nsIXULWindow);
-        }
-        catch(ex) { }
-      ]]></constructor>
-
-      <method name="_menuItemOnCommand">
-        <parameter name="aEvent"/>
-        <body><![CDATA[
-          var tabcontainer = document.getBindingParent(this);
-          tabcontainer.selectedItem = aEvent.target.tab;
-        ]]></body>
-      </method>
-
-      <method name="_tabOnAttrModified">
-        <parameter name="aEvent"/>
-        <body><![CDATA[
-          var menuItem = aEvent.target.mCorrespondingMenuitem;
-          if (menuItem) {
-            var attrName = aEvent.attrName;
-            switch (attrName) {
-              case "label":
-              case "crop":
-              case "busy":
-              case "image":
-              case "selected":
-                if (aEvent.attrChange == aEvent.REMOVAL)
-                  menuItem.removeAttribute(attrName);
-                else
-                  menuItem.setAttribute(attrName, aEvent.newValue);
-            }
-          }
-        ]]></body>
-      </method>
-
-      <method name="_tabOnTabClose">
-        <parameter name="aEvent"/>
-        <body><![CDATA[
-          var menuItem = aEvent.target.mCorrespondingMenuitem;
-          if (menuItem)
-            this.removeChild(menuItem);
-        ]]></body>
-      </method>
-
-      <method name="handleEvent">
-        <parameter name="aEvent"/>
-        <body><![CDATA[
-          if (!aEvent.isTrusted)
-            return;
-
-          switch (aEvent.type) {
-            case "command":
-              this._menuItemOnCommand(aEvent);
-              break;
-            case "DOMAttrModified":
-              this._tabOnAttrModified(aEvent);
-              break;
-            case "TabClose":
-              this._tabOnTabClose(aEvent);
-              break;
-            case "TabOpen":
-              this._createTabMenuItem(aEvent.originalTarget);
-              break;
-            case "scroll":
-              this._updateTabsVisibilityStatus();
-              break;
-          }
-        ]]></body>
-      </method>
-
-      <method name="_updateTabsVisibilityStatus">
-        <body><![CDATA[
-          var tabContainer = document.getBindingParent(this);
-          // We don't want menu item decoration unless there is overflow.
-          if (tabContainer.getAttribute("overflow") != "true")
-            return;
-
-          var tabstripBO = tabContainer.mTabstrip.scrollBoxObject;
-          for (var i = 0; i < this.childNodes.length; i++) {
-            var curTabBO = this.childNodes[i].tab.boxObject;
-            if (curTabBO.screenX >= tabstripBO.screenX &&
-                curTabBO.screenX + curTabBO.width <= tabstripBO.screenX + tabstripBO.width)
-              this.childNodes[i].setAttribute("tabIsVisible", "true"); 
-            else
-              this.childNodes[i].removeAttribute("tabIsVisible");
-          }
-        ]]></body>
-      </method>
-
-      <method name="_createTabMenuItem">
-        <parameter name="aTab"/>
-        <body><![CDATA[
-          var menuItem = document.createElementNS(
-            "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", 
-            "menuitem");
-
-          menuItem.setAttribute("class", "menuitem-iconic alltabs-item");
-
-          menuItem.setAttribute("label", aTab.label);
-          menuItem.setAttribute("crop", aTab.getAttribute("crop"));
-          menuItem.setAttribute("image", aTab.getAttribute("image"));
-
-          if (aTab.hasAttribute("busy"))
-            menuItem.setAttribute("busy", aTab.getAttribute("busy"));
-          if (aTab.selected)
-            menuItem.setAttribute("selected", "true");
-
-          // Keep some attributes of the menuitem in sync with its
-          // corresponding tab (e.g. the tab label)
-          aTab.mCorrespondingMenuitem = menuItem;
-          aTab.addEventListener("DOMAttrModified", this, false);
-          aTab.addEventListener("TabClose", this, false);
-          menuItem.tab = aTab;
-          menuItem.addEventListener("command", this, false);
-
-          this.appendChild(menuItem);
-          return menuItem;
-        ]]></body>
-      </method>
-    </implementation>
-
-    <handlers>
-      <handler event="popupshowing">
-      <![CDATA[
-        // set up the menu popup
-        var tabcontainer = document.getBindingParent(this);
-        var tabs = tabcontainer.childNodes;
-
-        // Listen for changes in the tab bar.
-        var tabbrowser = document.getBindingParent(tabcontainer);
-        tabbrowser.addEventListener("TabOpen", this, false);
-        tabcontainer.mTabstrip.addEventListener("scroll", this, false);
-
-        // if an animation is in progress and the user
-        // clicks on the "all tabs" button, stop the animation
-        tabcontainer._stopAnimation();
-
-        for (var i = 0; i < tabs.length; i++) {
-          this._createTabMenuItem(tabs[i]);
-        }
-        this._updateTabsVisibilityStatus();
-      ]]></handler>
-
-      <handler event="popuphiding">
-      <![CDATA[
-        // clear out the menu popup and remove the listeners
-        while (this.hasChildNodes()) {
-          var menuItem = this.lastChild;
-          menuItem.removeEventListener("command", this, false);
-          menuItem.tab.removeEventListener("DOMAttrModified", this, false);
-          menuItem.tab.removeEventListener("TabClose", this, false);
-          menuItem.tab.mCorrespondingMenuitem = null;
-          this.removeChild(menuItem);
-        }
-        var tabcontainer = document.getBindingParent(this);
-        tabcontainer.mTabstrip.removeEventListener("scroll", this, false);
-        document.getBindingParent(tabcontainer).removeEventListener("TabOpen", this, false);
-      ]]></handler>
-
-      <handler event="DOMMenuItemActive">
-      <![CDATA[
-        if (!this._xulWindow || !this._xulWindow.XULBrowserWindow)
-          return;
-
-        var tab = event.target.tab;
-        if (tab) {
-          var statusText = tab.linkedBrowser.currentURI.spec;
-          if (statusText == "about:blank") {
-            // XXXhack: Passing a space here (and not "")
-            // to make sure the the browser implementation would
-            // still consider it a hovered link.
-            statusText = " ";
-          }
-
-          this._xulWindow.XULBrowserWindow.setOverLink(statusText, null);
-        }
-      ]]></handler>
-
-      <handler event="DOMMenuItemInactive">
-      <![CDATA[
-        if (!this._xulWindow || !this._xulWindow.XULBrowserWindow)
-          return;
-
-        this._xulWindow.XULBrowserWindow.setOverLink("", null);
-      ]]></handler>
     </handlers>
   </binding>
 
   <!-- close-tab-button binding
        This binding relies on the structure of the tabbrowser binding.
        Therefore it should only be used as a child of the tab or the tabs
        element (in both cases, when they are anonymous nodes of <tabbrowser>).
        This binding is exposed as a pseudo-public-API so themes can customize
@@ -3352,17 +3119,16 @@
              closetabtext="&closeTab.label;">
       <xul:image xbl:inherits="validate,src=image" class="tab-icon-image"/>
       <xul:label flex="1" xbl:inherits="value=label,crop,accesskey" class="tab-text"/>
       <xul:toolbarbutton anonid="close-button" tabindex="-1" class="tab-close-button"/>
     </content>
 
     <implementation>
       <field name="mOverCloseButton">false</field>
-      <field name="mCorrespondingMenuitem">null</field>
     </implementation>
 
     <handlers>
       <handler event="mouseover">
         var anonid = event.originalTarget.getAttribute("anonid");
         if (anonid == "close-button")
           this.mOverCloseButton = true;
       </handler>
--- a/browser/base/content/test/browser_ctrlTab.js
+++ b/browser/base/content/test/browser_ctrlTab.js
@@ -111,19 +111,16 @@ function test() {
        is(gBrowser.tabContainer.selectedIndex, indexStart,
          "Selected tab doesn't change while tabbing");
     }
 
     if (tabCount > 2) {
       ok(isOpen(),
          "With " + tabCount + " tabs open, Ctrl+Tab opens the preview panel");
 
-      is(ctrlTab.label.value, gBrowser.mTabs[expectedIndex].label,
-         "Preview panel displays label of expected tab");
-
       releaseCtrl();
 
       ok(!isOpen(),
          "Releasing Ctrl closes the preview panel");
     } else {
       ok(!isOpen(),
          "With " + tabCount + " tabs open, Ctrl+Tab doesn't open the preview panel");
     }
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -17,16 +17,17 @@ browser.jar:
 *       content/browser/aboutRobots.xhtml             (content/aboutRobots.xhtml)
         content/browser/aboutRobots-icon.png          (content/aboutRobots-icon.png)
         content/browser/aboutRobots-icon-rtl.png      (content/aboutRobots-icon-rtl.png)
         content/browser/aboutRobots-widget-left.png   (content/aboutRobots-widget-left.png)
         content/browser/aboutRobots-widget-right.png  (content/aboutRobots-widget-right.png)
 *       content/browser/browser.css                   (content/browser.css)
 *       content/browser/browser.js                    (content/browser.js)
 *       content/browser/browser.xul                   (content/browser.xul)
+*       content/browser/browser-tabPreviews.xml       (content/browser-tabPreviews.xml)
 *       content/browser/credits.xhtml                 (content/credits.xhtml)
 *       content/browser/EULA.js                       (content/EULA.js)
 *       content/browser/EULA.xhtml                    (content/EULA.xhtml)
 *       content/browser/EULA.xul                      (content/EULA.xul)
 *       content/browser/metaData.js                   (content/metaData.js)
 *       content/browser/metaData.xul                  (content/metaData.xul)
 *       content/browser/pageinfo/pageInfo.xul         (content/pageinfo/pageInfo.xul)
 *       content/browser/pageinfo/pageInfo.js          (content/pageinfo/pageInfo.js)
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -421,8 +421,10 @@ The layout of the identity dialog preven
 substitution variables.  If it is difficult to translate the sense of the string
 with that structure, consider a translation which ignores the preceding domain and
 just addresses the organization to follow, e.g. "This site is run by " -->
 <!ENTITY identity.runBy "which is run by">
 
 <!ENTITY identity.moreInfoLinkText "More Information…">
 
 <!ENTITY downloadMonitor2.tooltip "Click to open downloads window">
+
+<!ENTITY ctrlTab.search.emptyText "Search Tabs">
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -1295,32 +1295,19 @@ tabpanels {
   margin: 0px;
 }
 
 .tabs-alltabs-box-animate {
   background-color: Highlight;
   opacity: 0.0;
 }
 
-/* All tabs menupopup */
-.alltabs-item > .menu-iconic-left > .menu-iconic-icon {
-  list-style-image: url("chrome://global/skin/icons/folder-item.png");
-  -moz-image-region: rect(0px, 16px, 16px, 0px);
-}
-
-.alltabs-item[selected="true"] {
-  font-weight: bold;
-}
-
-.alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {
-  list-style-image: url("chrome://global/skin/icons/loading_16.png");
-}
-
 .tabs-alltabs-button > .toolbarbutton-icon {
-   margin: 0px;
+  list-style-image: url("chrome://browser/skin/tabbrowser/alltabs.png");
+  margin: 2px 0 2px;
 }
 
 /* Sidebar */
 #sidebar-box .tabs-closebutton {
   margin-bottom: 0px !important;
   padding: 0px 2px 0px 2px !important;
 }
 
@@ -1367,42 +1354,46 @@ toolbar[mode="text"] > #window-controls 
 }
 
 #download-monitor {
   list-style-image: url("chrome://browser/skin/Toolbar-small.png");
   -moz-image-region: rect(0px 16px 16px 0px);
 }
 
 /* ::::: Ctrl-Tab Panel ::::: */
-#ctrlTab-label {
-  font-weight: bold;
-  font-size: 1.5em;
-  text-align: center;
-  margin-top: 1em;
-  margin-bottom: 1.5em;
+#ctrlTab-panel {
+  padding-top: 15px;
+}
+
+#ctrlTab-search {
+  margin: 0 0 15px;
 }
 
 .ctrlTab-thumbnail {
-  margin-bottom: 40px;
-  -moz-box-shadow: 1px 2px 3px ThreeDShadow;
+  margin-bottom: 15px;
+  cursor: pointer;
 }
- 
-.ctrlTab-thumbnail[selected="true"] {
-  -moz-box-shadow: 1px 2px 3px ThreeDShadow, 0 0 10px Highlight, 0 0 20px Highlight, 0 0 25px Highlight, 0 0 30px Highlight;
+
+.ctrlTab-thumbnail > html|canvas {
+  border: 1px solid ThreeDShadow;
+  margin: -1px;
 }
- 
-#ctrlTab-pages {
-  display: block;
-  text-align: center;
+
+.ctrlTab-thumbnail[selected="true"] ,
+.ctrlTab-thumbnail:hover {
+  background: Highlight;
+  color: HighlightText;
+  -moz-box-shadow: 0 0 2px Highlight, 0 0 2px Highlight, 0 0 3px Highlight, 0 0 4px Highlight, 0 0 10px Highlight, 0 0 15px Highlight;
 }
  
 .ctrlTab-pagePointer {
-  display: inline-block;
   margin: 0 1em 1em;
   width: 1.5em;
   height: 1.5em;
   -moz-border-radius: .75em;
   background: ThreeDShadow;
+  cursor: pointer;
 }
 
 .ctrlTab-pagePointer[selected="true"] {
   background: ThreeDDarkShadow;
+  cursor: default;
 }
--- a/browser/themes/gnomestripe/browser/jar.mn
+++ b/browser/themes/gnomestripe/browser/jar.mn
@@ -59,12 +59,13 @@ classic.jar:
   skin/classic/browser/places/unsortedBookmarks.png   (places/unsortedBookmarks.png)
   skin/classic/browser/places/wrench.png              (places/wrench.png)
   skin/classic/browser/preferences/alwaysAsk.png      (preferences/alwaysAsk.png)
   skin/classic/browser/preferences/application.png    (preferences/application.png)
   skin/classic/browser/preferences/mail.png           (preferences/mail.png)
   skin/classic/browser/preferences/Options.png        (preferences/Options.png)
 * skin/classic/browser/preferences/preferences.css    (preferences/preferences.css)
   skin/classic/browser/preferences/applications.css   (preferences/applications.css)
+  skin/classic/browser/tabbrowser/alltabs.png          (tabbrowser/alltabs.png)
   skin/classic/browser/tabbrowser/newtab.png           (tabbrowser/newtab.png)
   skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
   icon.png
   preview.png
new file mode 100644
index 0000000000000000000000000000000000000000..538bb6b344662adcfd7387bf2b97c752de649457
GIT binary patch
literal 171
zc%17D@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4v6p!Iy0TyAWZ~t}xvp_|El`NF
zz$3Dlfq_2}gc(=ZFV6%DvZOouIx;Y9?C1WI$O`0JdAc};RNP9=$;kL|zJaBo#w{nw
zN5QSO)>gu~QO(RyjZKM>yCWkf=g0&H@nn~6e4H`v;>j|8^B5W8=BWJNwZ|3Y6b4UM
KKbLh*2~7YSt}MX-
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -1743,20 +1743,16 @@ tabbrowser > tabbox > tabpanels {
   background-color: transparent !important;
 }
 
 
 /**
  * New Tab & All Tabs Buttons
  */
 
-.tabs-alltabs-box {
-  margin: 0;
-}
-
 .tabs-newtab-button ,
 .tabs-alltabs-button {
   -moz-border-start: 2px solid;
   -moz-border-end: none;
   -moz-border-left-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
   -moz-border-right-colors: rgba(0,0,0,0.25) rgba(255,255,255,0.15);
   margin: 0;
   padding: 0 4px;
@@ -1768,55 +1764,37 @@ tabbrowser > tabbox > tabpanels {
   padding-top: 2px;
   list-style-image: url(chrome://browser/skin/tabbrowser/alltabs-box-bkgnd-icon.png);
 }
 .tabs-newtab-button:hover ,
 .tabs-alltabs-button:hover {
   background-color: rgba(0,0,0,0.10);
 }
 .tabs-newtab-button:hover:active,
-.tabs-alltabs-button:hover:active,
-.tabs-alltabs-button[open="true"] {
+.tabs-alltabs-button:hover:active {
   background-color: rgba(0,0,0,0.20);
 }
 
 .tabs-newtab-button > .toolbarbutton-text ,
-.tabs-alltabs-button > .toolbarbutton-menu-dropmarker ,
 .tabs-alltabs-button > .toolbarbutton-text {
   display: none;
 }
 
 .tabs-alltabs-button > .toolbarbutton-icon {
   -moz-margin-end: 2px;
 }
 
 .tabs-alltabs-box-animate {
   margin: 1px 0px 0px 0px;
   width: 25px;
   background-image: url("chrome://browser/skin/tabbrowser/alltabs-box-overflow-bkgnd-animate.png");
   background-repeat: no-repeat;
   opacity: 0.0;
 }
 
-/**
- * All Tabs Menupopup 
- */
-
-.alltabs-item > .menu-iconic-left > .menu-iconic-icon {
-  list-style-image: url("chrome://global/skin/tree/item.png");
-}
-
-.alltabs-item[selected="true"] {
-  font-weight: bold;
-}
-
-.alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {
-  list-style-image: url("chrome://global/skin/icons/loading_16.png") !important;
-}
-
 .tabs-closebutton {
   padding-right: 4px;
   list-style-image: url("chrome://global/skin/icons/closetab.png") !important;
   list-style-image: none;
   border: none;
   -moz-box-align: stretch;
 }
 
@@ -2138,50 +2116,58 @@ tabpanels.plain {
   background: rgba(68, 68, 68, .9) url(KUI-background.png) repeat-x;
   color: white;
   border: 1px solid rgba(255, 255, 255, 0.15);
   -moz-border-radius: 10px;
   margin-top: -1px;
   margin-left: -1px;
 }
 
-.KUI-panel[level="top"] {
+.KUI-panel[level="top"] ,
+#ctrlTab-panel:not([sticky]) {
   background-color: rgba(68, 68, 68, .5);
   -moz-window-shadow: none;
 }
 
 /* ::::: Ctrl-Tab Panel ::::: */
-#ctrlTab-label {
-  font-weight: bold;
-  font-size: 1.5em;
-  text-align: center;
-  margin-top: 1em;
-  margin-bottom: 1.5em;
-  text-shadow: black 0 0 1em;
+#ctrlTab-panel {
+  padding-top: 20px;
+  font-size: 1.2em;
+  text-shadow: 0 0 3px black, 0 0 3px black;
+}
+
+#ctrlTab-search {
+  margin: 0 0 20px;
 }
 
 .ctrlTab-thumbnail {
-  margin-bottom: 40px;
-  -moz-box-shadow: 1px 2px 3px black;
+  margin-bottom: 20px;
+  cursor: pointer;
+  font-weight: bold;
 }
 
-.ctrlTab-thumbnail[selected="true"] {
-  -moz-box-shadow: 1px 2px 3px black, 0 0 10px white, 0 0 20px rgb(50, 170, 255), 0 0 30px rgb(50, 170, 255);
+.ctrlTab-thumbnail > html|canvas {
+  border: 2px solid white;
+  margin: -2px;
 }
 
-#ctrlTab-pages {
-  display: block;
-  text-align: center;
+.ctrlTab-thumbnail[selected="true"] ,
+.ctrlTab-thumbnail:hover {
+  background: Highlight;
+  color: HighlightText;
+  -moz-box-shadow: 0 0 2px Highlight, 0 0 2px Highlight, 0 0 3px Highlight, 0 0 4px Highlight, 0 0 10px Highlight, 0 0 20px white;
+  text-shadow: 0 0 3px transparent;
 }
 
 .ctrlTab-pagePointer {
-  display: inline-block;
   margin: 0 1em 1em;
   width: 1.5em;
   height: 1.5em;
   -moz-border-radius: .75em;
   background: rgba(0, 0, 0, .5);
   border: 1px solid rgba(255, 255, 255, .3);
+  cursor: pointer;
 }
 
 .ctrlTab-pagePointer[selected="true"] {
   background: rgba(255, 255, 255, .6);
+  cursor: default;
 }
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -82,17 +82,13 @@
   z-index: 10;
 }
 
 #ctrlTab-panel:-moz-system-metric(windows-compositor) {
   background: transparent;
   -moz-appearance: -moz-win-glass;
   -moz-border-radius: 0;
   border: none;
-}
-
-#ctrlTab-label:-moz-system-metric(windows-compositor) {
-  font: Segoe UI, window;
+  font: "Segoe UI", window;
   font-weight: normal;
-  font-size: 1.5em;
   color: black;
-  text-shadow: white -1px -1px 9px, white -1px 1px 9px, white 1px 1px 9px, white 1px -1px 9px;
+  text-shadow: white -1px -1px .5em, white -1px 1px .5em, white 1px 1px .5em, white 1px -1px .5em;
 }
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -1518,52 +1518,39 @@ tabpanels {
 
 .tabs-newtab-button > .toolbarbutton-icon {
   list-style-image: url(chrome://browser/skin/tabbrowser/newtab.png);
   margin: 3px 0 0;
   -moz-margin-end: 2px;
 }
 
 .tabs-newtab-button > .toolbarbutton-text,
-.tabs-alltabs-button > .toolbarbutton-text,
-.tabs-alltabs-button > .toolbarbutton-icon {
+.tabs-alltabs-button > .toolbarbutton-text {
   display: none;
 }
 
-.tabs-alltabs-button > .toolbarbutton-menu-dropmarker {
-  margin: 2px 1px 2px 0px;
+.tabs-alltabs-button > .toolbarbutton-icon {
+  list-style-image: url("chrome://browser/skin/tabbrowser/alltabs.png");
+  margin: 6px 0 4px;
+  -moz-image-region: auto;
 }
 
 .tabs-alltabs-box-animate {
   margin-top: 2px;
   margin-bottom: 4px;
   width: 18px !important;
   background-image: url("chrome://browser/skin/tabbrowser/alltabs-box-overflow-end-bkgnd-animate.png");
   background-repeat: no-repeat;
   opacity: 0.0;
 }
 
 stack[chromedir="rtl"] > hbox > .tabs-alltabs-box-animate {
   background-image: url("chrome://browser/skin/tabbrowser/alltabs-box-overflow-start-bkgnd-animate.png");
 }
 
-/* All tabs menupopup */
-.alltabs-item > .menu-iconic-left > .menu-iconic-icon {
-  list-style-image: url("chrome://global/skin/icons/folder-item.png");
-  -moz-image-region: rect(0px, 16px, 16px, 0px);
-}
-
-.alltabs-item[selected="true"] {
-  font-weight: bold;
-}
-
-.alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {
-  list-style-image: url("chrome://global/skin/icons/loading_16.png");
-}
-
 /* Tabstrip close button */
 .tabs-closebutton {
   -moz-appearance: none;
   list-style-image: url("chrome://global/skin/icons/close.png");
   -moz-image-region: rect(0px, 14px, 14px, 0px);
   padding: 4px 2px;
   margin: 0px;
   border: none;
@@ -1995,50 +1982,58 @@ toolbarbutton.bookmark-item[dragover="tr
   background: rgba(68, 68, 68, .9) url(KUI-background.png) repeat-x;
   color: white;
   border: 1px solid rgba(255, 255, 255, 0.15);
   -moz-border-radius: 10px;
   margin-top: -1px;
   margin-left: -1px;
 }
 
-.KUI-panel[level="top"] {
+.KUI-panel[level="top"] ,
+#ctrlTab-panel:not([sticky]) {
   background-color: rgba(68, 68, 68, .5);
   -moz-window-shadow: none;
 }
 
 /* ::::: Ctrl-Tab Panel ::::: */
-#ctrlTab-label {
-  font-weight: bold;
-  font-size: 1.5em;
-  text-align: center;
-  margin-top: 1em;
-  margin-bottom: 1.5em;
-  text-shadow: black 0 0 1em;
+#ctrlTab-panel {
+  padding-top: 20px;
+  font-size: 1.2em;
+  text-shadow: 0 0 3px black, 0 0 3px black, 0 0 3px black;
+}
+
+#ctrlTab-search {
+  margin: 0 0 20px;
 }
 
 .ctrlTab-thumbnail {
-  margin-bottom: 40px;
-  -moz-box-shadow: 1px 2px 3px black;
+  margin-bottom: 20px;
+  cursor: pointer;
+  font-weight: bold;
 }
 
-.ctrlTab-thumbnail[selected="true"] {
-  -moz-box-shadow: 1px 2px 3px black, 0 0 10px white, 0 0 20px rgb(50, 170, 255), 0 0 30px rgb(50, 170, 255);
+.ctrlTab-thumbnail > html|canvas {
+  border: 2px solid white;
+  margin: -2px;
 }
 
-#ctrlTab-pages {
-  display: block;
-  text-align: center;
+.ctrlTab-thumbnail[selected="true"] ,
+.ctrlTab-thumbnail:hover {
+  background: Highlight;
+  color: HighlightText;
+  -moz-box-shadow: 0 0 2px Highlight, 0 0 2px Highlight, 0 0 3px Highlight, 0 0 4px Highlight, 0 0 10px Highlight, 0 0 20px white;
+  text-shadow: 0 0 3px transparent;
 }
 
 .ctrlTab-pagePointer {
-  display: inline-block;
   margin: 0 1em 1em;
   width: 1.5em;
   height: 1.5em;
   -moz-border-radius: .75em;
   background: rgba(0, 0, 0, .5);
   border: 1px solid rgba(255, 255, 255, .3);
+  cursor: pointer;
 }
 
 .ctrlTab-pagePointer[selected="true"] {
   background: rgba(255, 255, 255, .6);
+  cursor: default;
 }
--- a/browser/themes/winstripe/browser/jar.mn
+++ b/browser/themes/winstripe/browser/jar.mn
@@ -76,16 +76,17 @@ classic.jar:
         skin/classic/browser/places/searching_16.png                 (places/searching_16.png)
         skin/classic/browser/preferences/alwaysAsk.png               (preferences/alwaysAsk.png)
         skin/classic/browser/preferences/application.png             (preferences/application.png)
         skin/classic/browser/preferences/mail.png                    (preferences/mail.png)
         skin/classic/browser/preferences/Options.png                 (preferences/Options.png)
         skin/classic/browser/preferences/saveFile.png                (preferences/saveFile.png)
         skin/classic/browser/preferences/preferences.css             (preferences/preferences.css)
         skin/classic/browser/preferences/applications.css            (preferences/applications.css)
+        skin/classic/browser/tabbrowser/alltabs.png                             (tabbrowser/alltabs.png)
         skin/classic/browser/tabbrowser/alltabs-box-overflow-end-bkgnd-animate.png        (tabbrowser/alltabs-box-overflow-end-bkgnd-animate.png)
         skin/classic/browser/tabbrowser/alltabs-box-overflow-start-bkgnd-animate.png      (tabbrowser/alltabs-box-overflow-start-bkgnd-animate.png)
         skin/classic/browser/tabbrowser/newtab.png                              (tabbrowser/newtab.png)
         skin/classic/browser/tabbrowser/tab-arrow-end.png                       (tabbrowser/tab-arrow-end.png)
         skin/classic/browser/tabbrowser/tab-arrow-start.png                     (tabbrowser/tab-arrow-start.png)
         skin/classic/browser/tabbrowser/tabbrowser-tabs-bkgnd.png               (tabbrowser/tabbrowser-tabs-bkgnd.png)
         skin/classic/browser/tabbrowser/tabDragIndicator.png                    (tabbrowser/tabDragIndicator.png)
         skin/classic/browser/tabbrowser/tab-bkgnd.png                           (tabbrowser/tab-bkgnd.png)
@@ -171,16 +172,17 @@ classic.jar:
         skin/classic/aero/browser/preferences/alwaysAsk.png          (preferences/alwaysAsk-aero.png)
         skin/classic/aero/browser/preferences/application.png        (preferences/application-aero.png)
         skin/classic/aero/browser/preferences/mail.png               (preferences/mail-aero.png)
         skin/classic/aero/browser/preferences/Options.png            (preferences/Options-aero.png)
         skin/classic/aero/browser/preferences/plugin.png             (preferences/plugin-aero.png)
         skin/classic/aero/browser/preferences/saveFile.png           (preferences/saveFile-aero.png)
         skin/classic/aero/browser/preferences/preferences.css        (preferences/preferences.css)
         skin/classic/aero/browser/preferences/applications.css       (preferences/applications.css)
+        skin/classic/aero/browser/tabbrowser/alltabs.png                        (tabbrowser/alltabs.png)
         skin/classic/aero/browser/tabbrowser/alltabs-box-overflow-end-bkgnd-animate.png   (tabbrowser/alltabs-box-overflow-end-bkgnd-animate.png)
         skin/classic/aero/browser/tabbrowser/alltabs-box-overflow-start-bkgnd-animate.png (tabbrowser/alltabs-box-overflow-start-bkgnd-animate.png)
         skin/classic/aero/browser/tabbrowser/newtab.png                         (tabbrowser/newtab-aero.png)
         skin/classic/aero/browser/tabbrowser/tab-arrow-end.png                  (tabbrowser/tab-arrow-end-aero.png)
         skin/classic/aero/browser/tabbrowser/tab-arrow-start.png                (tabbrowser/tab-arrow-start-aero.png)
         skin/classic/aero/browser/tabbrowser/tabbrowser-tabs-bkgnd.png          (tabbrowser/tabbrowser-tabs-bkgnd.png)
         skin/classic/aero/browser/tabbrowser/tabDragIndicator.png               (tabbrowser/tabDragIndicator-aero.png)
         skin/classic/aero/browser/tabbrowser/tab-bkgnd.png                      (tabbrowser/tab-bkgnd.png)
deleted file mode 100755
index 883ad64f1ace86344e37f7d87cf2b5bc6dffca2e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100755
index e6a06de857359884c2bccec26152c8fdbf3c6de8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100755
index 0561d67bae469587b3b115996fc7aec8bd33b31a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100755
index 05ef810c161d1cf1a855940279b63bacd727ad0a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index 0000000000000000000000000000000000000000..538bb6b344662adcfd7387bf2b97c752de649457
GIT binary patch
literal 171
zc%17D@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4v6p!Iy0TyAWZ~t}xvp_|El`NF
zz$3Dlfq_2}gc(=ZFV6%DvZOouIx;Y9?C1WI$O`0JdAc};RNP9=$;kL|zJaBo#w{nw
zN5QSO)>gu~QO(RyjZKM>yCWkf=g0&H@nn~6e4H`v;>j|8^B5W8=BWJNwZ|3Y6b4UM
KKbLh*2~7YSt}MX-