Aviary branch landing

This commit is contained in:
ben@bengoodger.com 2007-08-21 21:59:41 -07:00
parent 7ea2f1fb60
commit 0e1a25372e

View File

@ -51,7 +51,7 @@
<content> <content>
<xul:stringbundle src="chrome://global/locale/tabbrowser.properties"/> <xul:stringbundle src="chrome://global/locale/tabbrowser.properties"/>
<xul:tabbox flex="1" xbl:inherits="handleCtrlPageUpDown" eventnode="document" <xul:tabbox flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown"
onselect="if (!('updateCurrentBrowser' in this.parentNode) || event.target.localName != 'tabpanels') return; this.parentNode.updateCurrentBrowser();"> onselect="if (!('updateCurrentBrowser' in this.parentNode) || event.target.localName != 'tabpanels') return; this.parentNode.updateCurrentBrowser();">
<xul:hbox class="tabbrowser-strip chromeclass-toolbar" collapsed="true" tooltip="_child" context="_child"> <xul:hbox class="tabbrowser-strip chromeclass-toolbar" collapsed="true" tooltip="_child" context="_child">
<xul:tooltip onpopupshowing="event.preventBubble(); if (document.tooltipNode.hasAttribute('label')) { this.setAttribute('label', document.tooltipNode.getAttribute('label')); return true; } return false;"/> <xul:tooltip onpopupshowing="event.preventBubble(); if (document.tooltipNode.hasAttribute('label')) { this.setAttribute('label', document.tooltipNode.getAttribute('label')); return true; } return false;"/>
@ -80,6 +80,7 @@
<xul:tabs class="tabbrowser-tabs" closebutton="true" flex="1" <xul:tabs class="tabbrowser-tabs" closebutton="true" flex="1"
setfocus="false" setfocus="false"
onclick="this.parentNode.parentNode.parentNode.onTabClick(event);" onclick="this.parentNode.parentNode.parentNode.onTabClick(event);"
onmousedown="this.parentNode.parentNode.parentNode.updateContextTab(event);"
ondragover="nsDragAndDrop.dragOver(event, this.parentNode.parentNode.parentNode); ondragover="nsDragAndDrop.dragOver(event, this.parentNode.parentNode.parentNode);
event.stopPropagation();" event.stopPropagation();"
ondragdrop="nsDragAndDrop.drop(event, this.parentNode.parentNode.parentNode); ondragdrop="nsDragAndDrop.drop(event, this.parentNode.parentNode.parentNode);
@ -98,7 +99,11 @@
</xul:tabs> </xul:tabs>
</xul:hbox> </xul:hbox>
<xul:tabpanels flex="1" class="plain"> <xul:tabpanels flex="1" class="plain">
<xul:browser type="content-primary" disablehistory="true" xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup"/> <xul:vbox flex="1">
<xul:browsermessage hidden="true" type="top"/>
<xul:browser flex="1" type="content-primary" message="true" disablehistory="true" xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup"/>
<xul:browsermessage hidden="true" type="bottom"/>
</xul:vbox>
</xul:tabpanels> </xul:tabpanels>
</xul:tabbox> </xul:tabbox>
<children/> <children/>
@ -155,6 +160,86 @@
false false
</field> </field>
<method name="getBrowserAtIndex">
<parameter name="aIndex"/>
<body>
<![CDATA[
return this.mPanelContainer.childNodes[aIndex].firstChild.nextSibling;
]]>
</body>
</method>
<method name="getBrowserIndexForDocument">
<parameter name="aDocument"/>
<body>
<![CDATA[
for (var i = 0; i < this.mPanelContainer.childNodes.length; i++) {
if (this.getBrowserAtIndex(i).contentDocument == aDocument) {
return i;
}
}
return -1;
]]>
</body>
</method>
<method name="getMessageForBrowser">
<parameter name="aBrowser"/>
<parameter name="aTopBottom"/>
<body>
<![CDATA[
return aBrowser[aTopBottom == "top" ? "previousSibling" : "nextSibling"];
]]>
</body>
</method>
<method name="showMessage">
<parameter name="aBrowser"/>
<parameter name="aIconURL"/>
<parameter name="aMessage"/>
<parameter name="aButtonLabel"/>
<parameter name="aDocShell"/>
<parameter name="aSource"/>
<parameter name="aPopup"/>
<parameter name="aTopBottom"/>
<parameter name="aShowCloseButton"/>
<body>
<![CDATA[
var message = this.getMessageForBrowser(aBrowser, aTopBottom);
message.image = aIconURL;
message.text = aMessage;
message.buttonText = aButtonLabel;
message.hidden = false;
if (aSource) {
message.source = aSource;
message.popup = null;
}
else if (aPopup) {
message.popup = aPopup;
message.source = null;
}
message.docShell = aDocShell;
message.closeButton = aShowCloseButton;
aBrowser.isShowingMessage = true;
]]>
</body>
</method>
<method name="hideMessage">
<parameter name="aBrowser"/>
<parameter name="aTopBottom"/>
<body>
<![CDATA[
if (aTopBottom != "both")
this.getMessageForBrowser(aBrowser, aTopBottom).hidden = true;
else {
this.getMessageForBrowser(aBrowser, "top").hidden = true;
this.getMessageForBrowser(aBrowser, "bottom").hidden = true;
}
]]>
</body>
</method>
<!-- A web progress listener object definition for a given tab. --> <!-- A web progress listener object definition for a given tab. -->
<method name="mTabProgressListener"> <method name="mTabProgressListener">
<parameter name="aTab"/> <parameter name="aTab"/>
@ -167,7 +252,8 @@
mTab: aTab, mTab: aTab,
mBrowser: aBrowser, mBrowser: aBrowser,
mBlank: aStartsBlank, mBlank: aStartsBlank,
mIcon: "", mIcon: null,
mLastURI: null,
onProgressChange : function (aWebProgress, aRequest, onProgressChange : function (aWebProgress, aRequest,
aCurSelfProgress, aMaxSelfProgress, aCurSelfProgress, aMaxSelfProgress,
@ -194,6 +280,9 @@
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener; const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
const nsIChannel = Components.interfaces.nsIChannel; const nsIChannel = Components.interfaces.nsIChannel;
if (aStateFlags & nsIWebProgressListener.STATE_START)
this.mBrowser.mFavIconURL = null;
if (aStateFlags & nsIWebProgressListener.STATE_START && if (aStateFlags & nsIWebProgressListener.STATE_START &&
aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) { aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
// It's okay to clear what the user typed when we start // It's okay to clear what the user typed when we start
@ -208,7 +297,7 @@
this.mTab.setAttribute("busy", "true"); this.mTab.setAttribute("busy", "true");
this.mTab.label = this.mTabBrowser.mStringBundle.getString("tabs.loading"); this.mTab.label = this.mTabBrowser.mStringBundle.getString("tabs.loading");
this.mTab.removeAttribute("image"); this.mTab.removeAttribute("image");
this.mIcon = ""; this.mIcon = null;
if (this.mTabBrowser.mCurrentTab == this.mTab) if (this.mTabBrowser.mCurrentTab == this.mTab)
this.mTabBrowser.mIsBusy = true; this.mTabBrowser.mIsBusy = true;
@ -227,12 +316,17 @@
this.mTab.removeAttribute("busy"); this.mTab.removeAttribute("busy");
var location = aRequest.QueryInterface(nsIChannel).URI; var location = aRequest.QueryInterface(nsIChannel).URI;
if (this.mIcon) {
// For keyword URIs clear the user typed value since they will be changed into real URIs
if (location.scheme == "keyword")
this.mBrowser.userTypedValue = null;
if (this.mTabBrowser.shouldLoadFavIcon(location)) {
if (this.mIcon)
this.mTab.setAttribute("image", this.mIcon); this.mTab.setAttribute("image", this.mIcon);
this.mIcon = ""; else
}
else if (this.mTabBrowser.shouldLoadFavIcon(location))
this.mTabBrowser.loadFavIcon(location, "image", this.mTab); this.mTabBrowser.loadFavIcon(location, "image", this.mTab);
}
if (this.mTab.label == this.mTabBrowser.mStringBundle.getString("tabs.loading")) if (this.mTab.label == this.mTabBrowser.mStringBundle.getString("tabs.loading"))
this.mTabBrowser.setTabTitle(this.mTab); this.mTabBrowser.setTabTitle(this.mTab);
@ -248,10 +342,10 @@
p.onStateChange(aWebProgress, aRequest, aStateFlags, aStatus); p.onStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
} }
} }
}, }
,
onLocationChange : function(aWebProgress, aRequest, aLocation) onLocationChange : function(aWebProgress, aRequest, aLocation) {
{
// The document loaded correctly, clear the value if we should // The document loaded correctly, clear the value if we should
if (this.mBrowser.userTypedClear) if (this.mBrowser.userTypedClear)
this.mBrowser.userTypedValue = null; this.mBrowser.userTypedValue = null;
@ -265,8 +359,7 @@
} }
}, },
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {
{
if (this.mBlank) if (this.mBlank)
return; return;
@ -298,6 +391,7 @@
return this; return this;
throw Components.results.NS_NOINTERFACE; throw Components.results.NS_NOINTERFACE;
} }
}); });
]]> ]]>
</body> </body>
@ -331,13 +425,8 @@
<body> <body>
<![CDATA[ <![CDATA[
var iconURL = this.buildFavIconString(aURI); var iconURL = this.buildFavIconString(aURI);
var entry = this.openCacheEntry(iconURL, Components.interfaces.nsICache.ACCESS_READ); if (!this.isFavIconKnownMissing(iconURL))
if (!entry)
aElt.setAttribute(aAttr, iconURL); aElt.setAttribute(aAttr, iconURL);
else {
entry.close();
entry = null;
}
]]> ]]>
</body> </body>
</method> </method>
@ -380,6 +469,20 @@
</body> </body>
</method> </method>
<method name="isFavIconKnownMissing">
<parameter name="key"/>
<body>
<![CDATA[
var e = this.openCacheEntry(key, Components.interfaces.nsICache.ACCESS_READ);
if (e) {
e.close();
return true;
}
return false;
]]>
</body>
</method>
<method name="updateTitlebar"> <method name="updateTitlebar">
<body> <body>
<![CDATA[ <![CDATA[
@ -400,7 +503,19 @@
newTitle += sep; newTitle += sep;
} }
newTitle += modifier; newTitle += modifier;
this.ownerDocument.title = newTitle; window.title = newTitle;
]]>
</body>
</method>
<method name="updateContextTab">
<parameter name="aEvent"/>
<body>
<![CDATA[
if (aEvent.originalTarget.localName == "tab")
this.mContextTab = aEvent.originalTarget;
else
this.mContextTab = document.popupNode;
]]> ]]>
</body> </body>
</method> </method>
@ -409,7 +524,6 @@
<parameter name="aPopupMenu"/> <parameter name="aPopupMenu"/>
<body> <body>
<![CDATA[ <![CDATA[
this.mContextTab = document.popupNode;
var disabled = this.mPanelContainer.childNodes.length == 1; var disabled = this.mPanelContainer.childNodes.length == 1;
var menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple"); var menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-multiple");
for (var i = 0; i < menuItems.length; i++) for (var i = 0; i < menuItems.length; i++)
@ -421,17 +535,13 @@
<method name="updateCurrentBrowser"> <method name="updateCurrentBrowser">
<body> <body>
<![CDATA[ <![CDATA[
var newBrowser = this.mPanelContainer.childNodes[this.mPanelContainer.selectedIndex]; var newBrowser = this.getBrowserAtIndex(this.mPanelContainer.selectedIndex);
if (this.mCurrentBrowser == newBrowser) if (this.mCurrentBrowser == newBrowser)
return; return;
if (this.mCurrentBrowser) { if (this.mCurrentBrowser) {
this.mCurrentBrowser.focusedWindow = document.commandDispatcher.focusedWindow; this.mCurrentBrowser.focusedWindow = document.commandDispatcher.focusedWindow;
this.mCurrentBrowser.focusedElement = document.commandDispatcher.focusedElement; this.mCurrentBrowser.focusedElement = document.commandDispatcher.focusedElement;
if (this.mCurrentBrowser.focusedElement) {
// Clear focus outline before we draw on top of it
this.mCurrentBrowser.focusedElement.blur();
}
this.mCurrentBrowser.setAttribute("type", "content"); this.mCurrentBrowser.setAttribute("type", "content");
} }
@ -467,12 +577,18 @@
if (securityUI) if (securityUI)
p.onSecurityChange(webProgress, null, securityUI.state); p.onSecurityChange(webProgress, null, securityUI.state);
var listener = this.mTabListeners[this.mPanelContainer.selectedIndex]; var listener = this.mTabListeners[this.mPanelContainer.selectedIndex];
if (listener.mIcon) if (listener.mIcon) {
if (this.isFavIconKnownMissing(listener.mIcon))
listener.mIcon = null;
else
p.onLinkIconAvailable(newBrowser, listener.mIcon); p.onLinkIconAvailable(newBrowser, listener.mIcon);
} }
} }
}
this.mCurrentBrowser.userTypedClear = userTypedClear; this.mCurrentBrowser.userTypedClear = userTypedClear;
this._fastFind.setDocShell(this.mCurrentBrowser.docShell);
// Update the window title. // Update the window title.
this.updateTitlebar(); this.updateTitlebar();
@ -501,35 +617,24 @@
} }
} }
if (document.commandDispatcher.focusedElement && function setFocus(element) {
document.commandDispatcher.focusedElement.parentNode == Components.lookupMethod(element, "focus").call(element);
this.mCurrentTab.parentNode) {
// The focus is on a tab in the same tab panel
return; // If focus was on a tab, switching tabs focuses the new tab
} }
var whatToFocus = window.content;
// Focus the previously focused element or window // Focus the previously focused element or window
if (newBrowser.focusedElement) {
if (newBrowser.focusedElement.parentNode !=
this.mCurrentTab.parentNode) {
// Focus the remembered element unless it's in the current tab panel
whatToFocus = newBrowser.focusedElement;
}
}
else if (newBrowser.focusedWindow) {
whatToFocus = newBrowser.focusedWindow;
}
function setFocus(element) {
document.commandDispatcher.suppressFocusScroll = true; document.commandDispatcher.suppressFocusScroll = true;
Components.lookupMethod(element, "focus").call(element); if (newBrowser.focusedElement) {
document.commandDispatcher.suppressFocusScroll = false; try {
setFocus(newBrowser.focusedElement);
} catch (e) {
setFocus(newBrowser.focusedWindow);
} }
}
// Use setTimeout to avoid focus outline ghosting. else if (newBrowser.focusedWindow)
setTimeout(setFocus, 0, whatToFocus); setFocus(newBrowser.focusedWindow);
else // new tab, focus our new content area
setTimeout(setFocus, 0, window.content);
document.commandDispatcher.suppressFocusScroll = false;
]]> ]]>
</body> </body>
</method> </method>
@ -614,31 +719,25 @@
null) != nsIContentPolicy.ACCEPT) null) != nsIContentPolicy.ACCEPT)
return; return;
// var browserIndex = tabBrowser.getBrowserIndexForDocument(targetDoc); var browserIndex = tabBrowser.getBrowserIndexForDocument(targetDoc);
var browserIndex = -1;
if (tabBrowser.mTabbedMode) {
for (var i = 0; i < tabBrowser.mPanelContainer.childNodes.length; i++) {
if (tabBrowser.mPanelContainer.childNodes[i].contentDocument == targetDoc) {
browserIndex = i;
break;
}
}
} else {
if (tabBrowser.mCurrentBrowser.contentDocument == targetDoc)
browserIndex = 0;
}
// no browser? no favicon. // no browser? no favicon.
if (browserIndex == -1) if (browserIndex == -1)
return; return;
var listener = tabBrowser.mTabListeners[browserIndex]; var listener = tabBrowser.mTabListeners[browserIndex];
// there's no tab listener for non-tabbed mode browser 0 // there's no tab listener for non-tabbed mode browser 0
if (tabBrowser.isFavIconKnownMissing(href)) {
if (listener)
listener.mIcon = null;
return;
}
if (listener) if (listener)
listener.mIcon = href; listener.mIcon = href;
if (tabBrowser.mProgressListeners) { if (tabBrowser.mProgressListeners) {
var targetBrowser = tabBrowser.mTabbedMode ? tabBrowser.mPanelContainer.childNodes[i] : tabBrowser.mCurrentBrowser; var targetBrowser = tabBrowser.getBrowserAtIndex(browserIndex);
for (i = 0; i < tabBrowser.mProgressListeners.length; i++) { for (i = 0; i < tabBrowser.mProgressListeners.length; i++) {
var p = tabBrowser.mProgressListeners[i]; var p = tabBrowser.mProgressListeners[i];
if (p) if (p)
@ -657,14 +756,14 @@
return; return;
var i = 0; var i = 0;
for ( ; i < this.parentNode.childNodes.length; i++) { for ( ; i < this.parentNode.parentNode.childNodes.length; i++) {
if (this.parentNode.childNodes[i] == this) if (this.parentNode.parentNode.childNodes[i].firstChild.nextSibling == this)
break; break;
} }
var tabBrowser = this.parentNode.parentNode.parentNode; var tabBrowser = this.parentNode.parentNode.parentNode.parentNode;
var tab = tabBrowser.mTabContainer.childNodes[i];
var tab = tabBrowser.mTabContainer.childNodes[i];
tabBrowser.setTabTitle(tab); tabBrowser.setTabTitle(tab);
if (tab == tabBrowser.mCurrentTab) if (tab == tabBrowser.mCurrentTab)
@ -760,15 +859,26 @@
} }
// Wire up a progress listener to our filter. // Wire up a progress listener to our filter.
const listener = this.mTabProgressListener(this.mCurrentTab, const listener = this.mTabProgressListener(this.mCurrentTab, this.mCurrentBrowser, false);
this.mCurrentBrowser,
false);
filter.addProgressListener(listener, Components.interfaces.nsIWebProgress.NOTIFY_ALL); filter.addProgressListener(listener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
this.mTabListeners[0] = listener; this.mTabListeners[0] = listener;
]]> ]]>
</body> </body>
</method> </method>
<method name="_createMessage">
<parameter name="aType"/>
<body>
<![CDATA[
var message = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"browsermessage");
message.hidden = true;
message.setAttribute("type", aType);
return message;
]]>
</body>
</method>
<method name="addTab"> <method name="addTab">
<parameter name="aURI"/> <parameter name="aURI"/>
<parameter name="aReferrerURI"/> <parameter name="aReferrerURI"/>
@ -776,14 +886,16 @@
<parameter name="aPostData"/> <parameter name="aPostData"/>
<body> <body>
<![CDATA[ <![CDATA[
var blank = (aURI == "about:blank");
if (!this.mTabbedMode) if (!this.mTabbedMode)
this.enterTabbedMode(); this.enterTabbedMode();
var b = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"browser");
var t = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", var t = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"tab"); "tab");
var blank = (aURI == "about:blank");
if (blank) if (blank)
t.setAttribute("label", this.mStringBundle.getString("tabs.untitled")); t.setAttribute("label", this.mStringBundle.getString("tabs.untitled"));
else else
@ -798,14 +910,21 @@
t.setAttribute("onerror", "this.parentNode.parentNode.parentNode.parentNode.addToMissedIconCache(this.getAttribute('image')); this.removeAttribute('image');"); t.setAttribute("onerror", "this.parentNode.parentNode.parentNode.parentNode.addToMissedIconCache(this.getAttribute('image')); this.removeAttribute('image');");
this.mTabContainer.appendChild(t); this.mTabContainer.appendChild(t);
var b = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"browser");
b.setAttribute("type", "content"); b.setAttribute("type", "content");
b.setAttribute("message", "true");
b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu")); b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
b.setAttribute("tooltip", this.getAttribute("contenttooltip")); b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup")); b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
this.mPanelContainer.appendChild(b); // Add the Message and the Browser to the box
var vbox = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"vbox");
vbox.setAttribute("flex", "1");
vbox.appendChild(this._createMessage("top"));
vbox.appendChild(b);
vbox.appendChild(this._createMessage("bottom"));
b.setAttribute("flex", "1");
this.mPanelContainer.appendChild(vbox);
b.addEventListener("DOMTitleChanged", this.onTitleChanged, false); b.addEventListener("DOMTitleChanged", this.onTitleChanged, false);
@ -824,6 +943,8 @@
this.mTabListeners[position] = tabListener; this.mTabListeners[position] = tabListener;
this.mTabFilters[position] = filter; this.mTabFilters[position] = filter;
b._fastFind = this.fastFind;
if (!blank) { if (!blank) {
// pretend the user typed this so it'll be available till // pretend the user typed this so it'll be available till
// the document successfully loads // the document successfully loads
@ -840,20 +961,69 @@
</body> </body>
</method> </method>
<method name="warnAboutClosingTabs">
<parameter name="aAll"/>
<body>
<![CDATA[
var numTabs = this.mTabContainer.childNodes.length;
var reallyClose = true;
if (numTabs <= 1)
return reallyClose;
const pref = "browser.tabs.warnOnClose";
var shouldPrompt = this.mPrefs.getBoolPref(pref);
var reallyClose = true;
if (shouldPrompt) {
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
//default to true: if it were false, we wouldn't get this far
var warnOnClose = { value:true };
var bundle = this.mStringBundle;
var tabsToClose = numTabs; //number of tabs to be removed
if (!aAll)
--tabsToClose;
var messageKey = (tabsToClose == 1) ? "tabs.closeWarningOne" : "tabs.closeWarningMultiple";
var closeKey = (tabsToClose == 1) ? "tabs.closeButtonOne" : "tabs.closeButtonMultiple";
var buttonPressed = promptService.confirmEx(window,
bundle.getString('tabs.closeWarningTitle'),
bundle.getFormattedString(messageKey, [tabsToClose]),
(promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0)
+ (promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1),
bundle.getString(closeKey),
null, null,
bundle.getString('tabs.closeWarningPromptMe'),
warnOnClose);
reallyClose = (buttonPressed == 0);
// don't set the pref unless they press OK and it's false
if (reallyClose && !warnOnClose.value)
this.mPrefs.setBoolPref(pref, false);
}
return reallyClose;
]]>
</body>
</method>
<method name="removeAllTabsBut"> <method name="removeAllTabsBut">
<parameter name="aTab"/> <parameter name="aTab"/>
<body> <body>
<![CDATA[ <![CDATA[
if (this.warnAboutClosingTabs(false)) {
if (aTab.localName != "tab") if (aTab.localName != "tab")
aTab = this.mCurrentTab; aTab = this.mCurrentTab;
else else
this.mTabContainer.selectedItem = aTab; this.mTabContainer.selectedItem = aTab;
var childNodes = this.mTabContainer.childNodes; var childNodes = this.mTabContainer.childNodes;
for (var i = childNodes.length - 1; i >= 0; --i) { for (var i = childNodes.length - 1; i >= 0; --i) {
if (childNodes[i] != aTab) if (childNodes[i] != aTab)
this.removeTab(childNodes[i]); this.removeTab(childNodes[i]);
} }
}
}
]]> ]]>
</body> </body>
</method> </method>
@ -875,6 +1045,11 @@
var l = this.mTabContainer.childNodes.length; var l = this.mTabContainer.childNodes.length;
if (l == 1) { if (l == 1) {
if (!this.mPrefs.getBoolPref("browser.tabs.autoHide")) {
// blank the tab
this.loadURI("about:blank");
return;
}
// hide the tab bar // hide the tab bar
this.mPrefs.setBoolPref("browser.tabs.forceHide", true); this.mPrefs.setBoolPref("browser.tabs.forceHide", true);
this.setStripVisibilityTo(false); this.setStripVisibilityTo(false);
@ -904,7 +1079,7 @@
// Remove the tab's filter and progress listener. // Remove the tab's filter and progress listener.
const filter = this.mTabFilters[index]; const filter = this.mTabFilters[index];
var oldBrowser = this.mPanelContainer.childNodes[index]; var oldBrowser = this.getBrowserAtIndex(index);
oldBrowser.webProgress.removeProgressListener(filter); oldBrowser.webProgress.removeProgressListener(filter);
filter.removeProgressListener(this.mTabListeners[index]); filter.removeProgressListener(this.mTabListeners[index]);
this.mTabFilters.splice(index, 1); this.mTabFilters.splice(index, 1);
@ -938,7 +1113,7 @@
oldBrowser.destroy(); oldBrowser.destroy();
this.mTabContainer.removeChild(oldTab); this.mTabContainer.removeChild(oldTab);
this.mPanelContainer.removeChild(oldBrowser); this.mPanelContainer.removeChild(this.mPanelContainer.childNodes[index]);
this.selectedTab = this.mTabContainer.childNodes[newIndex]; this.selectedTab = this.mTabContainer.childNodes[newIndex];
this.mPanelContainer.selectedIndex = newIndex; this.mPanelContainer.selectedIndex = newIndex;
@ -955,7 +1130,7 @@
var l = this.mPanelContainer.childNodes.length; var l = this.mPanelContainer.childNodes.length;
for (var i = 0; i < l; i++) { for (var i = 0; i < l; i++) {
try { try {
this.mPanelContainer.childNodes[i].reload(); this.getBrowserAtIndex(i).reload();
} catch (e) { } catch (e) {
// ignore failure to reload so others will be reloaded // ignore failure to reload so others will be reloaded
} }
@ -1058,7 +1233,7 @@
for (var i = 0; i < this.mTabContainer.childNodes.length; i++) { for (var i = 0; i < this.mTabContainer.childNodes.length; i++) {
if (this.mTabContainer.childNodes[i] == aTab) { if (this.mTabContainer.childNodes[i] == aTab) {
return this.mPanelContainer.childNodes[i]; return this.getBrowserAtIndex(i);
} }
} }
@ -1092,7 +1267,7 @@
<property name="browsers" <property name="browsers"
onget="return this.mPanelContainer.childNodes;" onget="return this.mPanelContainer.getElementsByTagName('browser');"
readonly="true"/> readonly="true"/>
<!-- Drag and drop observer API --> <!-- Drag and drop observer API -->
@ -1265,9 +1440,8 @@
<method name="attachFormFill"> <method name="attachFormFill">
<body><![CDATA[ <body><![CDATA[
var browsers = this.mPanelContainer.childNodes; for (var i = 0; i < this.mPanelContainer.childNodes.length; ++i) {
for (var i = 0; i < browsers.length; ++i) { var cb = this.getBrowserAtIndex(i);
var cb = browsers[i];
cb.attachFormFill(); cb.attachFormFill();
} }
]]></body> ]]></body>
@ -1275,9 +1449,8 @@
<method name="detachFormFill"> <method name="detachFormFill">
<body><![CDATA[ <body><![CDATA[
var browsers = this.mPanelContainer.childNodes; for (var i = 0; i < this.mPanelContainer.childNodes.length; ++i) {
for (var i = 0; i < browsers.length; ++i) { var cb = this.getBrowserAtIndex(i);
var cb = browsers[i];
cb.detachFormFill(); cb.detachFormFill();
} }
]]></body> ]]></body>
@ -1291,6 +1464,25 @@
onget="return this.mCurrentBrowser.currentURI;" onget="return this.mCurrentBrowser.currentURI;"
readonly="true"/> readonly="true"/>
<field name="_fastFind">null</field>
<property name="fastFind"
readonly="true">
<getter>
<![CDATA[
if (!this._fastFind) {
this._fastFind = Components.classes["@mozilla.org/typeaheadfind;1"]
.createInstance(Components.interfaces.nsITypeAheadFind);
this._fastFind.init(this.docShell);
}
return this._fastFind;
]]>
</getter>
</property>
<property name="findString"
onget="return this.mCurrentBrowser.findString;"
readonly="true"/>
<property name="docShell" <property name="docShell"
onget="return this.mCurrentBrowser.docShell" onget="return this.mCurrentBrowser.docShell"
readonly="true"/> readonly="true"/>
@ -1366,6 +1558,20 @@
]]> ]]>
</body> </body>
</method> </method>
<field name="_keyEventHandler" readonly="true">
<![CDATA[({
tabbrowser: this,
handleEvent: function handleEvent(aEvent) {
if (!aEvent.isTrusted) {
// Don't let untrusted events mess with tabs.
return;
}
if (aEvent.ctrlKey && aEvent.keyCode == KeyEvent.DOM_VK_F4 && this.tabbrowser.mTabBox.handleCtrlPageUpDown)
this.tabbrowser.removeCurrentTab();
}
})]]>
</field>
<property name="canFindAgain" <property name="canFindAgain"
onget="return this.mCurrentBrowser.canFindAgain;" onget="return this.mCurrentBrowser.canFindAgain;"
@ -1384,49 +1590,55 @@
<constructor> <constructor>
<![CDATA[ <![CDATA[
this.mCurrentBrowser = this.mPanelContainer.firstChild; this.mCurrentBrowser = this.getBrowserAtIndex(0);
this.mCurrentTab = this.mTabContainer.firstChild; this.mCurrentTab = this.mTabContainer.firstChild;
this.mTabBox.handleCtrlTab = !/Mac/.test(navigator.platform); document.addEventListener("keypress", this._keyEventHandler, false);
]]> ]]>
</constructor> </constructor>
<destructor> <destructor>
<![CDATA[ <![CDATA[
for (var i = 0; i < this.mTabListeners.length; ++i) { for (var i = 0; i < this.mTabListeners.length; ++i) {
this.mPanelContainer.childNodes[i].webProgress.removeProgressListener(this.mTabFilters[i]); this.getBrowserAtIndex(i).webProgress.removeProgressListener(this.mTabFilters[i]);
this.mTabFilters[i].removeProgressListener(this.mTabListeners[i]); this.mTabFilters[i].removeProgressListener(this.mTabListeners[i]);
this.mTabFilters[i] = null; this.mTabFilters[i] = null;
this.mTabListeners[i] = null; this.mTabListeners[i] = null;
this.mPanelContainer.childNodes[i].removeEventListener("DOMTitleChanged", this.onTitleChanged, false); this.getBrowserAtIndex(i).removeEventListener("DOMTitleChanged", this.onTitleChanged, false);
} }
this.mPanelContainer.removeEventListener("DOMLinkAdded", this.onLinkAdded, false); this.mPanelContainer.removeEventListener("DOMLinkAdded", this.onLinkAdded, false);
document.removeEventListener("keypress", this._keyEventHandler, false);
]]> ]]>
</destructor> </destructor>
</implementation> </implementation>
<handlers> <handlers>
<handler event="keypress" modifiers="control" keycode="VK_F4">
<![CDATA[
if (this.mTabBox.handleCtrlPageUpDown)
this.removeCurrentTab();
]]>
</handler>
<handler event="DOMWindowClose"> <handler event="DOMWindowClose">
<![CDATA[ <![CDATA[
if (!event.isTrusted) if (!event.isTrusted)
return; return;
const browsers = this.browsers; const browsers = this.mPanelContainer.childNodes;
if (browsers.length == 1) if (browsers.length == 1) {
// There's only one browser left. If a window is being
// closed and the window is *not* the window in the
// browser that's still around, prevent the event's default
// action to prevent closing a window that's being closed
// already.
if (this.getBrowserAtIndex(0).contentWindow != event.target)
event.preventDefault();
return; return;
}
var i = 0; var i = 0;
for (; i < browsers.length; ++i) { for (; i < browsers.length; ++i) {
if (browsers[i].contentWindow == event.target) if (this.getBrowserAtIndex(i).contentWindow == event.target) {
break;
}
this.removeTab(this.mTabContainer.childNodes[i]); this.removeTab(this.mTabContainer.childNodes[i]);
event.preventDefault(); event.preventDefault();
break;
}
}
]]> ]]>
</handler> </handler>
<handler event="DOMWillOpenModalDialog"> <handler event="DOMWillOpenModalDialog">