diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index 15c442d39f53..b9093342d9dd 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -341,7 +341,6 @@ pref("browser.tabs.selectOwnerOnClose", true);
pref("browser.ctrlTab.mostRecentlyUsed", true);
pref("browser.ctrlTab.recentlyUsedLimit", 7);
-pref("browser.ctrlTab.smoothScroll", true);
// Default bookmark sorting
pref("browser.bookmarks.sort.direction", "descending");
diff --git a/browser/base/content/browser-tabPreviews.js b/browser/base/content/browser-tabPreviews.js
index f003158da03f..931a7460f823 100644
--- a/browser/base/content/browser-tabPreviews.js
+++ b/browser/base/content/browser-tabPreviews.js
@@ -77,12 +77,11 @@ var tabPreviews = {
ctx.drawWindow(win, win.scrollX, win.scrollY,
snippetWidth, snippetWidth * this.aspectRatio, "rgb(255,255,255)");
- var data = thumbnail.toDataURL("image/jpeg", "quality=60");
if (aStore) {
- aTab.__thumbnail = data;
+ aTab.__thumbnail = thumbnail;
aTab.__thumbnail_lastURI = aTab.linkedBrowser.currentURI.spec;
}
- return data;
+ return thumbnail;
},
handleEvent: function (event) {
switch (event.type) {
@@ -114,8 +113,6 @@ var tabPreviews = {
* Ctrl-Tab panel
*/
var ctrlTab = {
- visibleCount: 3,
- _uniqid: 0,
get panel () {
delete this.panel;
return this.panel = document.getElementById("ctrlTab-panel");
@@ -124,29 +121,18 @@ var ctrlTab = {
delete this.label;
return this.label = document.getElementById("ctrlTab-label");
},
- get svgRoot () {
- delete this.svgRoot;
-
- let (groundFade = document.getElementById("ctrlTab-groundFade")) {
- groundFade.setAttribute("height", Math.ceil(tabPreviews.height * .25) + 1);
- groundFade.setAttribute("y", tabPreviews.height + 1);
- }
-
- this.svgRoot = document.getElementById("ctrlTab-svgRoot");
- this.svgRoot.setAttribute("height", tabPreviews.height * 1.25 + 2);
- return this.svgRoot;
+ get pagesBar () {
+ delete this.pagesBar;
+ return this.pagesBar = document.getElementById("ctrlTab-pages");
},
- get container () {
- delete this.container;
- return this.container = document.getElementById("ctrlTab-container");
+ get thumbnails () {
+ delete this.thumbnails;
+ return this.thumbnails = this.panel.getElementsByClassName("ctrlTab-thumbnail");
},
- get rtl () {
- delete this.rtl;
- return this.rtl = getComputedStyle(this.panel, "").direction == "rtl";
- },
- get iconSize () {
- delete this.iconSize;
- return this.iconSize = Math.max(16, Math.round(tabPreviews.height / 5));
+ get columns () {
+ delete this.columns;
+ return this.columns = this.thumbnails.length /
+ this.panel.getElementsByClassName("ctrlTab-row").length;
},
get closeCharCode () {
delete this.closeCharCode;
@@ -158,24 +144,43 @@ var ctrlTab = {
delete this.recentlyUsedLimit;
return this.recentlyUsedLimit = gPrefService.getIntPref("browser.ctrlTab.recentlyUsedLimit");
},
- get smoothScroll () {
- delete this.smoothScroll;
- return this.smoothScroll = gPrefService.getBoolPref("browser.ctrlTab.smoothScroll");
+ 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) {
+ 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 tabCount () {
- return gBrowser.mTabs.length;
- },
- get offscreenStart () {
- return Array.indexOf(this.container.childNodes, this.selected) - 1;
- },
- get offscreenEnd () {
- return this.container.childNodes.length - this.visibleCount - this.offscreenStart;
- },
- get offsetX () {
- return - tabPreviews.width * (this.rtl ? this.offscreenEnd : this.offscreenStart);
- },
- get isOpen () {
- return this.panel.state == "open" || this.panel.state == "showing";
+ get 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;
},
init: function () {
if (this._recentlyUsedTabs)
@@ -200,246 +205,128 @@ var ctrlTab = {
this.panel.removeEventListener("popuphiding", this, false);
document.removeEventListener("keypress", this, false);
+ gBrowser.mTabBox.handleCtrlTab = true;
},
- addBox: function (aAtStart) {
- const SVGNS = "http://www.w3.org/2000/svg";
-
- var thumbnail = document.createElementNS(SVGNS, "image");
- thumbnail.setAttribute("class", "ctrlTab-thumbnail");
- thumbnail.setAttribute("height", tabPreviews.height);
- thumbnail.setAttribute("width", tabPreviews.width);
-
- var thumbnail_border = document.createElementNS(SVGNS, "rect");
- thumbnail_border.setAttribute("class", "ctrlTab-thumbnailborder");
- thumbnail_border.setAttribute("height", tabPreviews.height);
- thumbnail_border.setAttribute("width", tabPreviews.width);
-
- var icon = document.createElementNS(SVGNS, "image");
- icon.setAttribute("class", "ctrlTab-icon");
- icon.setAttribute("height", this.iconSize);
- icon.setAttribute("width", this.iconSize);
- icon.setAttribute("x", - this.iconSize * .2);
- icon.setAttribute("y", tabPreviews.height - this.iconSize * 1.2);
-
- var thumbnail_and_icon = document.createElementNS(SVGNS, "g");
- thumbnail_and_icon.appendChild(thumbnail);
- thumbnail_and_icon.appendChild(thumbnail_border);
- thumbnail_and_icon.appendChild(icon);
-
- var reflection = document.createElementNS(SVGNS, "use");
- reflection.setAttribute("class", "ctrlTab-reflection");
- var ref_scale = .5;
- reflection.setAttribute("transform", "scale(1,-" + ref_scale + ")");
- reflection.setAttribute("y", - ((1 / ref_scale + 1) * tabPreviews.height +
- (1 / ref_scale) * 2));
-
- var box = document.createElementNS(SVGNS, "g");
- box.setAttribute("class", "ctrlTab-box");
- box.setAttribute("onclick", "ctrlTab.pick(this);");
- box.appendChild(thumbnail_and_icon);
- box.appendChild(reflection);
-
- if (aAtStart)
- this.container.insertBefore(box, this.container.firstChild);
- else
- this.container.appendChild(box);
- return box;
- },
- removeBox: function (aBox) {
- this.container.removeChild(aBox);
- if (!Array.some(this.container.childNodes, function (box) box._tab == aBox._tab))
- aBox._tab.removeEventListener("DOMAttrModified", this, false);
- aBox._tab = null;
- },
- addPreview: function (aBox, aTab) {
- const XLinkNS = "http://www.w3.org/1999/xlink";
-
- aBox._tab = aTab;
- let (thumbnail = aBox.firstChild.firstChild)
- thumbnail.setAttributeNS(XLinkNS, "href", tabPreviews.get(aTab));
- this.updateIcon(aBox);
-
- aTab.addEventListener("DOMAttrModified", this, false);
-
- if (!aBox.firstChild.hasAttribute("id")) {
- // set up reflection
- this._uniqid++;
- aBox.firstChild.setAttribute("id", "ctrlTab-preview-" + this._uniqid);
- aBox.lastChild.setAttributeNS(XLinkNS, "href", "#ctrlTab-preview-" + this._uniqid);
+ buildPagesBar: function () {
+ 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);
}
},
- updateIcon: function (aBox) {
- const XLinkNS = "http://www.w3.org/1999/xlink";
- var url = aBox._tab.hasAttribute("busy") ?
- "chrome://global/skin/icons/loading_16.png" :
- aBox._tab.getAttribute("image");
- var icon = aBox.firstChild.lastChild;
- if (url)
- icon.setAttributeNS(XLinkNS, "href", url);
- else
- icon.removeAttributeNS(XLinkNS, "href");
+ goToPage: function (aPage, aIndex) {
+ if (this.page != aPage)
+ 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 () {
+ 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) {
+ 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");
+ } else {
+ aThumbnail.removeAttribute("valid");
+ }
+ aThumbnail.width = tabPreviews.width;
+ aThumbnail.height = tabPreviews.height;
},
tabAttrModified: function (aTab, aAttrName) {
switch (aAttrName) {
case "busy":
- case "image":
- Array.forEach(this.container.childNodes, function (box) {
- if (box._tab == aTab) {
- if (aAttrName == "busy")
- this.addPreview(box, aTab);
- else
- this.updateIcon(box);
- }
- }, this);
- break;
- case "label":
- case "crop":
- if (!this._scrollTimer) {
- let boxes = this.container.childNodes;
- for (let i = boxes.length - 1; i >= 0; i--) {
- if (boxes[i]._tab == aTab && boxes[i] == this.selected) {
- this.label[aAttrName == "label" ? "value" : aAttrName] =
- aTab.getAttribute(aAttrName);
- break;
- }
+ for (let i = this.thumbnails.length - 1; i >= 0; i--) {
+ if (this.thumbnails[i]._tab == aTab) {
+ this.updatePreview(this.thumbnails[i], aTab);
+ break;
}
}
break;
- }
- },
- scroll: function () {
- if (!this.smoothScroll) {
- this.advanceSelected();
- this.arrangeBoxes();
- return;
- }
-
- this.stopScroll();
- let (next = this.invertDirection ? this.selected.previousSibling : this.selected.nextSibling) {
- this.setStatusbarValue(next);
- this.label.value = next._tab.label;
- this.label.crop = next._tab.crop;
- }
-
- const FRAME_LENGTH = 40;
- var x = this.offsetX;
- var scrollAmounts = let (tenth = tabPreviews.width / (this.invertDirection == this.rtl ? -10 : 10))
- [3 * tenth, 4 * tenth, 2 * tenth, tenth];
-
- function processFrame(self, lateness) {
- lateness += FRAME_LENGTH / 2;
- do {
- x += scrollAmounts.shift();
- lateness -= FRAME_LENGTH;
- } while (lateness > 0 && scrollAmounts.length);
- self.container.setAttribute("transform", "translate("+ x +",0)");
- self.svgRoot.forceRedraw();
- if (!scrollAmounts.length)
- self.stopScroll();
- }
-
- this._scrollTimer = setInterval(processFrame, FRAME_LENGTH, this);
- processFrame(this, 0);
- },
- stopScroll: function () {
- if (this._scrollTimer) {
- clearInterval(this._scrollTimer);
- this._scrollTimer = 0;
- this.advanceSelected();
- this.arrangeBoxes();
+ case "label":
+ case "crop":
+ if (this.selected._tab == aTab)
+ this.label[aAttrName == "label" ? "value" : aAttrName] = aTab[aAttrName];
+ break;
}
},
advanceSelected: function () {
- // regardless of visibleCount, the new highlighted tab will be
- // the first or third-visible tab, depending on whether Shift is pressed
- var index = ((this.invertDirection ? 0 : 2) + this.offscreenStart + this.tabCount)
- % this.tabCount;
- if (index < 2)
- index += this.tabCount;
- if (index > this.container.childNodes.length - this.visibleCount + 1)
- index -= this.tabCount;
- this.selected = this.container.childNodes[index];
- },
- arrangeBoxes: function () {
- this.addOffscreenBox(this.invertDirection);
- this.addOffscreenBox(!this.invertDirection);
+ this.selected.removeAttribute("selected");
- // having lots of off-screen boxes reduces the scrolling speed, remove some
- for (let i = this.offscreenStart; i > 1; i--)
- this.removeBox(this.container.firstChild);
- for (let i = this.offscreenEnd; i > 1; i--)
- this.removeBox(this.container.lastChild);
-
- this.container.setAttribute("transform", "translate("+ this.offsetX +", 0)");
-
- for (let i = 0, l = this.container.childNodes.length; i < l; i++)
- this.arrange(i);
- },
- addOffscreenBox: function (aAtStart) {
- if (this.container.childNodes.length < this.tabCount + this.visibleCount + 1 &&
- !(aAtStart ? this.offscreenStart : this.offscreenEnd)) {
- let tabs = this.getTabList();
- let i = aAtStart ?
- tabs.indexOf(this.container.firstChild._tab) - 1:
- tabs.indexOf(this.container.lastChild._tab) + 1;
- i = (i + tabs.length) % tabs.length;
- this.addPreview(this.addBox(aAtStart), tabs[i]);
+ 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();
},
- arrange: function (aIndex) {
- var box = this.container.childNodes[aIndex];
- var selected = box == this.selected;
- if (selected) {
- box.setAttribute("selected", "true");
- this.setStatusbarValue(box);
- this.label.value = box._tab.label;
- this.label.crop = box._tab.crop;
+ 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 {
- box.removeAttribute("selected");
+ try {
+ url = decodeURI(url);
+ } catch (e) {}
}
- var scale = selected ? 1 : .75;
- var pos = this.rtl ? this.container.childNodes.length - 1 - aIndex : aIndex;
- var trans_x = tabPreviews.width * (pos + (1 - scale) / 2) / scale;
- var trans_y = (tabPreviews.height + 1) * (1 / scale - 1);
- box.setAttribute("transform", "scale(" + scale + "," + scale + ") " +
- "translate("+ trans_x + "," + trans_y + ")");
+ XULBrowserWindow.setOverLink(url, null);
},
- pick: function (aBox) {
- this.stopScroll();
- var selectedTab = (aBox || this.selected)._tab;
+ thumbnailClick: function (event) {
+ switch (event.button) {
+ case 0:
+ this.selectThumbnail(event.currentTarget);
+ break;
+ case 1:
+ gBrowser.removeTab(event.currentTarget._tab);
+ break;
+ }
+ },
+ selectThumbnail: function (aThumbnail) {
+ var selectedTab = (aThumbnail || this.selected)._tab;
this.panel.hidePopup();
gBrowser.selectedTab = selectedTab;
},
- setStatusbarValue: function (aBox) {
- var value = "";
- if (aBox) {
- value = aBox._tab.linkedBrowser.currentURI.spec;
- if (value == "about:blank") {
- // XXXhack: Passing a space here (and not "")
- // to make sure the browser implementation would
- // still consider it a hovered link.
- value = " ";
- } else {
- try {
- value = decodeURI(value);
- } catch (e) {}
- }
- }
- XULBrowserWindow.setOverLink(value, null);
- },
- getTabList: function () {
- var list = Array.slice(gBrowser.mTabs);
- for (let i = 0; i < gBrowser.tabContainer.selectedIndex; i++)
- list.push(list.shift());
- if (!this._useTabBarOrder && this.recentlyUsedLimit > 0) {
- let 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;
- },
attachTab: function (aTab, aPos) {
if (aPos == 0)
this._recentlyUsedTabs.unshift(aTab);
@@ -448,37 +335,35 @@ var ctrlTab = {
else
this._recentlyUsedTabs.push(aTab);
},
- detachTab: function (aTab) {
- var i = this._recentlyUsedTabs.indexOf(aTab);
+ detachTab: function (aTab, aTabs) {
+ var tabs = aTabs || this._recentlyUsedTabs;
+ var i = tabs.indexOf(aTab);
if (i >= 0)
- this._recentlyUsedTabs.splice(i, 1);
+ tabs.splice(i, 1);
},
open: function () {
+ if (window.allTabs)
+ allTabs.close();
+
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);
this.panel.addEventListener("popuphiding", this, false);
this.panel.hidden = false;
- this.panel.width = tabPreviews.width * this.visibleCount;
+ this.panel.width = screen.availWidth * .9;
this.panel.openPopupAtScreen(screen.availLeft + (screen.availWidth - this.panel.width) / 2,
- screen.availTop + (screen.availHeight - this.svgRoot.getAttribute("height")) / 2,
+ screen.availTop + screen.availHeight * .1,
false);
-
- // display $visibleCount tabs, starting with the first or
- // the second to the last tab, depending on whether Shift is pressed
- {
- let tabs = this.getTabList();
- let index = this.invertDirection ? tabs.length - 2 : 0;
- for (let i = this.visibleCount; i > 0; i--)
- this.addPreview(this.addBox(), tabs[index++ % tabs.length]);
- }
-
- // regardless of visibleCount, highlight the second-visible tab
- this.selected = this.container.childNodes[1];
- this.arrangeBoxes();
+ this.buildPagesBar();
+ this.selectedIndex = 0;
+ this.page = 0;
+ this.advanceSelected();
},
onKeyPress: function (event) {
var isOpen = this.isOpen;
@@ -489,22 +374,74 @@ var ctrlTab = {
propagate = false;
this.invertDirection = event.shiftKey;
if (isOpen)
- this.scroll();
+ this.advanceSelected();
else if (this.tabCount == 2)
- gBrowser.selectedTab = this.getTabList()[1];
+ gBrowser.selectedTab = this.tabList[1];
else if (this.tabCount > 2)
this.open();
}
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 {
+ this.selected.removeAttribute("selected");
+ this.selectedIndex = index;
+ this.updateSelected();
+ }
+ }
+ break;
+ case event.DOM_VK_DOWN:
+ if (isOpen) {
+ let index = this.selectedIndex + this.columns;
+ if (index >= this.thumbnails.length || !this.thumbnails[index].hasAttribute("valid")) {
+ this.goToPage(this.page + 1, this.selectedIndex % this.columns);
+ } else {
+ this.selected.removeAttribute("selected");
+ this.selectedIndex = index;
+ while (!this.selected.hasAttribute("valid"))
+ this.selectedIndex--;
+ this.updateSelected();
+ }
+ }
+ break;
+ case event.DOM_VK_LEFT:
+ if (isOpen) {
+ this.invertDirection = true;
+ this.advanceSelected();
+ }
+ break;
+ case event.DOM_VK_RIGHT:
+ if (isOpen) {
+ this.invertDirection = false;
+ this.advanceSelected();
+ }
+ break;
+ case event.DOM_VK_HOME:
+ if (isOpen)
+ this.goToPage(0);
+ break;
+ case event.DOM_VK_END:
+ if (isOpen)
+ this.goToPage(this.pages - 1, this.thumbnails.length - 1);
+ break;
+ 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_ESCAPE:
if (isOpen)
this.panel.hidePopup();
break;
default:
- if (isOpen && event.charCode == this.closeCharCode) {
- this.stopScroll();
+ if (isOpen && event.charCode == this.closeCharCode)
gBrowser.removeTab(this.selected._tab);
- }
}
if (!propagate) {
event.stopPropagation();
@@ -512,19 +449,23 @@ var ctrlTab = {
}
},
onPopupHiding: function () {
- this.stopScroll();
+ gBrowser.mTabBox.handleCtrlPageUpDown = this._tabBarHandlesCtrlPageUpDown;
document.removeEventListener("keyup", this, false);
document.removeEventListener("keydown", this, false);
- while (this.container.childNodes.length)
- this.removeBox(this.container.lastChild);
- this.selected = null;
+
+ 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.invertDirection = false;
this._useTabBarOrder = false;
- this._uniqid = 0;
this.label.value = "";
- this.setStatusbarValue();
- this.container.removeAttribute("transform");
- this.svgRoot.forceRedraw();
+ XULBrowserWindow.setOverLink("", null);
+ this._page = null;
this._deferOnTabSelect.forEach(this.onTabSelect, this);
this._deferOnTabSelect = null;
@@ -535,6 +476,20 @@ var ctrlTab = {
this.attachTab(aTab, 0);
}
},
+ removeClosingTabFromUI: function (aTab) {
+ this._closing = aTab;
+ 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) {
switch (event.type) {
case "DOMAttrModified":
@@ -551,23 +506,9 @@ var ctrlTab = {
this.attachTab(event.target, 1);
break;
case "TabClose":
- if (this.isOpen) {
- if (this.tabCount == 2) {
- // we have two tabs, one is being closed, so the panel isn't needed anymore
- this.panel.hidePopup();
- } else {
- if (event.target == this.selected._tab)
- this.advanceSelected();
- this.detachTab(event.target);
- Array.slice(this.container.childNodes).forEach(function (box) {
- if (box._tab == event.target) {
- this.removeBox(box);
- this.arrangeBoxes();
- }
- }, this);
- }
- }
this.detachTab(event.target);
+ if (this.isOpen)
+ this.removeClosingTabFromUI(event.target);
break;
case "keypress":
this.onKeyPress(event);
@@ -578,7 +519,7 @@ var ctrlTab = {
event.stopPropagation();
event.preventDefault();
if (event.type == "keyup" && event.keyCode == event.DOM_VK_CONTROL)
- this.pick();
+ this.selectThumbnail();
break;
case "popuphiding":
this.onPopupHiding();
diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css
index f303548fe67b..adcc43bc29ee 100644
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -1,6 +1,5 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-@namespace svg url("http://www.w3.org/2000/svg");
-@namespace xlink url("http://www.w3.org/1999/xlink");
+@namespace html url("http://www.w3.org/1999/xhtml");
searchbar {
-moz-binding: url("chrome://browser/content/search/search.xml#searchbar");
@@ -99,15 +98,6 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
}
/* Tab Previews */
-svg|*.ctrlTab-icon:not([xlink|href]) ,
-svg|*.ctrlTab-thumbnail:not([xlink|href]) {
- display: none;
-}
-
-svg|*.ctrlTab-thumbnailborder {
- fill: transparent;
-}
-
-svg|*.ctrlTab-icon {
- filter: url(chrome://browser/content/browser.xul#ctrlTab-iconShadow);
+.ctrlTab-thumbnail:not([valid]) {
+ visibility: hidden;
}
diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul
index 9cbd47a5dc30..35458313d681 100644
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -240,25 +240,22 @@
#endif
>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/browser/base/content/test/browser_ctrlTab.js b/browser/base/content/test/browser_ctrlTab.js
index f7a6d498bf1a..650387ce5ff8 100644
--- a/browser/base/content/test/browser_ctrlTab.js
+++ b/browser/base/content/test/browser_ctrlTab.js
@@ -49,7 +49,7 @@ function test() {
}
assertTabs(2);
- //ctrlTabTest([1], 1, 0);
+ ctrlTabTest([1], 1, 0);
gBrowser.removeTab(gBrowser.tabContainer.lastChild);
diff --git a/browser/themes/gnomestripe/browser/browser.css b/browser/themes/gnomestripe/browser/browser.css
index 88a955e6d334..16ab77ba2335 100644
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -47,7 +47,6 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
-@namespace svg url("http://www.w3.org/2000/svg");
#menubar-items {
-moz-box-orient: vertical; /* for flex hack */
@@ -1375,22 +1374,35 @@ toolbar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-text {
/* ::::: Ctrl-Tab Panel ::::: */
#ctrlTab-label {
font-weight: bold;
+ font-size: 1.5em;
text-align: center;
- margin-top: .5em;
- margin-bottom: .7em;
+ margin-top: 1em;
+ margin-bottom: 1.5em;
}
-svg|*.ctrlTab-thumbnailborder {
- stroke: ThreeDDarkShadow;
- stroke-width: .7px;
+.ctrlTab-thumbnail {
+ margin-bottom: 40px;
+ -moz-box-shadow: 1px 2px 3px ThreeDShadow;
+}
+
+.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-pages {
+ display: block;
+ text-align: center;
+}
+
+.ctrlTab-pagePointer {
+ display: inline-block;
+ margin: 0 1em 1em;
+ width: 1.5em;
+ height: 1.5em;
+ -moz-border-radius: .75em;
+ background: ThreeDShadow;
}
-svg|*#ctrlTab-fadeGradientTop {
- stop-color: ThreeDShadow;
- stop-opacity: .75;
-}
-
-svg|*#ctrlTab-fadeGradientBottom {
- stop-color: -moz-dialog;
- stop-opacity: 1;
+.ctrlTab-pagePointer[selected="true"] {
+ background: ThreeDDarkShadow;
}
diff --git a/browser/themes/pinstripe/browser/browser.css b/browser/themes/pinstripe/browser/browser.css
index a06765b591fe..b636042520d3 100755
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -45,7 +45,6 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
-@namespace svg url("http://www.w3.org/2000/svg");
#main-window[chromehidden~="toolbar"][chromehidden~="location"][chromehidden~="directories"] {
border-top: 1px solid rgba(0,0,0,0.65);
@@ -2136,41 +2135,53 @@ tabpanels.plain {
/* ::::: Keyboard UI Panel ::::: */
.KUI-panel {
-moz-appearance: none;
- background: rgba(0, 0, 0, .8) url(KUI-background.png) repeat-x;
+ background: rgba(68, 68, 68, .9) url(KUI-background.png) repeat-x;
color: white;
- border: 1px solid #ccc;
+ border: 1px solid rgba(255, 255, 255, 0.15);
-moz-border-radius: 10px;
margin-top: -1px;
margin-left: -1px;
+}
+
+.KUI-panel[level="top"] {
+ background-color: rgba(68, 68, 68, .5);
-moz-window-shadow: none;
}
/* ::::: Ctrl-Tab Panel ::::: */
-#ctrlTab-panel {
- margin-top: -20px;
- border-bottom-width: 9px;
- -moz-border-bottom-colors: #ccc black black black black black black black black;
-}
-
#ctrlTab-label {
font-weight: bold;
- font-size: 14px;
+ font-size: 1.5em;
text-align: center;
- margin-top: 6px;
- margin-bottom: 10px;
+ margin-top: 1em;
+ margin-bottom: 1.5em;
+ text-shadow: black 0 0 1em;
}
-svg|*.ctrlTab-thumbnailborder {
- stroke: white;
- stroke-width: 1px;
+.ctrlTab-thumbnail {
+ margin-bottom: 40px;
+ -moz-box-shadow: 1px 2px 3px black;
}
-svg|*#ctrlTab-fadeGradientTop {
- stop-color: black;
- stop-opacity: .5;
+.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);
}
-svg|*#ctrlTab-fadeGradientBottom {
- stop-color: black;
- stop-opacity: 1;
+#ctrlTab-pages {
+ display: block;
+ text-align: center;
+}
+
+.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);
+}
+
+.ctrlTab-pagePointer[selected="true"] {
+ background: rgba(255, 255, 255, .6);
}
diff --git a/browser/themes/winstripe/browser/browser-aero.css b/browser/themes/winstripe/browser/browser-aero.css
index ed9e2d58a426..a22d8f5aa4ed 100644
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -96,8 +96,3 @@
color: black;
text-shadow: white -1px -1px 9px, white -1px 1px 9px, white 1px 1px 9px, white 1px -1px 9px;
}
-
-svg|*#ctrlTab-groundFade:-moz-system-metric(windows-compositor),
-svg|*.ctrlTab-reflection:-moz-system-metric(windows-compositor) {
- display: none;
-}
diff --git a/browser/themes/winstripe/browser/browser.css b/browser/themes/winstripe/browser/browser.css
index 23e320bb83ac..44ea05c59b03 100644
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -45,7 +45,6 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
-@namespace svg url("http://www.w3.org/2000/svg");
#menubar-items {
-moz-box-orient: vertical; /* for flex hack */
@@ -1993,40 +1992,53 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
/* ::::: Keyboard UI Panel ::::: */
.KUI-panel {
-moz-appearance: none;
- background: rgba(0, 0, 0, .8) url(KUI-background.png) repeat-x;
+ background: rgba(68, 68, 68, .9) url(KUI-background.png) repeat-x;
color: white;
- border: 1px solid #ccc;
+ border: 1px solid rgba(255, 255, 255, 0.15);
-moz-border-radius: 10px;
margin-top: -1px;
margin-left: -1px;
}
-/* ::::: Ctrl-Tab Panel ::::: */
-#ctrlTab-panel {
- margin-top: -20px;
- border-bottom-width: 9px;
- -moz-border-bottom-colors: #ccc black black black black black black black black;
+.KUI-panel[level="top"] {
+ background-color: rgba(68, 68, 68, .5);
+ -moz-window-shadow: none;
}
+/* ::::: Ctrl-Tab Panel ::::: */
#ctrlTab-label {
font-weight: bold;
- font-size: 14px;
+ font-size: 1.5em;
text-align: center;
- margin-top: 6px;
- margin-bottom: 10px;
+ margin-top: 1em;
+ margin-bottom: 1.5em;
+ text-shadow: black 0 0 1em;
}
-svg|*.ctrlTab-thumbnailborder {
- stroke: white;
- stroke-width: 1px;
+.ctrlTab-thumbnail {
+ margin-bottom: 40px;
+ -moz-box-shadow: 1px 2px 3px black;
}
-svg|*#ctrlTab-fadeGradientTop {
- stop-color: black;
- stop-opacity: .5;
+.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);
}
-svg|*#ctrlTab-fadeGradientBottom {
- stop-color: black;
- stop-opacity: 1;
+#ctrlTab-pages {
+ display: block;
+ text-align: center;
+}
+
+.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);
+}
+
+.ctrlTab-pagePointer[selected="true"] {
+ background: rgba(255, 255, 255, .6);
}