Bug 436304 - Implement All Tabs panel with previews and search. r=connor

This commit is contained in:
Dão Gottwald 2008-11-05 08:38:13 +01:00
Родитель 954480d415
Коммит 96c0f71fcd
23 изменённых файлов: 390 добавлений и 469 удалений

Просмотреть файл

@ -339,7 +339,7 @@ pref("browser.tabs.closeButtons", 1);
// 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

Просмотреть файл

@ -43,19 +43,19 @@
*/
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;
@ -63,7 +63,7 @@ var tabPreviews = {
}
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;
@ -83,7 +83,7 @@ var tabPreviews = {
}
return thumbnail;
},
handleEvent: function (event) {
handleEvent: function tabPreviews__handleEvent(event) {
switch (event.type) {
case "TabSelect":
if (this._selectedTab &&
@ -117,9 +117,9 @@ var ctrlTab = {
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;
@ -138,7 +138,13 @@ var ctrlTab = {
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;
@ -147,10 +153,20 @@ var ctrlTab = {
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)
@ -165,12 +181,19 @@ var ctrlTab = {
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)
@ -180,9 +203,38 @@ var ctrlTab = {
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];
@ -192,10 +244,16 @@ var ctrlTab = {
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;
@ -204,10 +262,23 @@ var ctrlTab = {
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;
@ -220,9 +291,9 @@ var ctrlTab = {
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;
@ -233,13 +304,14 @@ var ctrlTab = {
}
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)
@ -256,14 +328,22 @@ var ctrlTab = {
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) {
@ -272,14 +352,10 @@ var ctrlTab = {
}
}
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;
@ -294,40 +370,20 @@ var ctrlTab = {
}
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)
@ -335,15 +391,19 @@ var ctrlTab = {
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)
@ -352,33 +412,52 @@ var ctrlTab = {
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:
@ -435,23 +514,31 @@ var ctrlTab = {
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)
@ -461,23 +548,34 @@ var ctrlTab = {
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 {
@ -490,7 +588,8 @@ var ctrlTab = {
}
this._closing = null;
},
handleEvent: function (event) {
handleEvent: function ctrlTab__handleEvent(event) {
switch (event.type) {
case "DOMAttrModified":
this.tabAttrModified(event.target, event.attrName);
@ -515,15 +614,34 @@ var ctrlTab = {
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;
}
}
};

Просмотреть файл

@ -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>

Просмотреть файл

@ -98,6 +98,19 @@ window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-m
}
/* 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;
}

Просмотреть файл

@ -1260,10 +1260,7 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
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.

Просмотреть файл

@ -233,27 +233,33 @@
<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>

Просмотреть файл

@ -12,10 +12,6 @@
}
%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");
}

Просмотреть файл

@ -2736,13 +2736,10 @@
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;">
@ -2935,11 +2932,6 @@
]]></body>
</method>
<field name="mAllTabsPopup">
document.getAnonymousElementByAttribute(this,
"anonid", "alltabs-popup");
</field>
<field name="mAllTabsBoxAnimate">
document.getAnonymousElementByAttribute(this,
"anonid",
@ -2952,11 +2944,6 @@
</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>
@ -3049,226 +3036,6 @@
</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>
@ -3357,7 +3124,6 @@
<implementation>
<field name="mOverCloseButton">false</field>
<field name="mCorrespondingMenuitem">null</field>
</implementation>
<handlers>

Просмотреть файл

@ -116,9 +116,6 @@ function test() {
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(),

Просмотреть файл

@ -22,6 +22,7 @@ browser.jar:
* 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)

Просмотреть файл

@ -426,3 +426,5 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY identity.moreInfoLinkText "More Information…">
<!ENTITY downloadMonitor2.tooltip "Click to open downloads window">
<!ENTITY ctrlTab.search.emptyText "Search Tabs">

Просмотреть файл

@ -1300,22 +1300,9 @@ tabpanels {
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 */
@ -1372,37 +1359,41 @@ 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: 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;
}

Просмотреть файл

@ -64,6 +64,7 @@ classic.jar:
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

Двоичные данные
browser/themes/gnomestripe/browser/tabbrowser/alltabs.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 171 B

Просмотреть файл

@ -1748,10 +1748,6 @@ tabbrowser > tabbox > tabpanels {
* New Tab & All Tabs Buttons
*/
.tabs-alltabs-box {
margin: 0;
}
.tabs-newtab-button ,
.tabs-alltabs-button {
-moz-border-start: 2px solid;
@ -1773,13 +1769,11 @@ tabbrowser > tabbox > tabpanels {
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;
}
@ -1796,22 +1790,6 @@ tabbrowser > tabbox > tabpanels {
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;
@ -2143,45 +2121,53 @@ tabpanels.plain {
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;
}

Просмотреть файл

@ -87,12 +87,8 @@
-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;
}

Просмотреть файл

@ -1523,13 +1523,14 @@ tabpanels {
}
.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 {
@ -1545,20 +1546,6 @@ 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;
@ -2000,45 +1987,53 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
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;
}

Просмотреть файл

@ -81,6 +81,7 @@ classic.jar:
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)
@ -176,6 +177,7 @@ classic.jar:
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)

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 460 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 348 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 466 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 365 B

Двоичные данные
browser/themes/winstripe/browser/tabbrowser/alltabs.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 171 B