зеркало из https://github.com/mozilla/pjs.git
Bug 225680 - Ability to detach tabs. r=mconnor, enn. a=beltzner.
This commit is contained in:
Родитель
d4b644f7d7
Коммит
02251f4f79
|
@ -863,7 +863,10 @@ function BrowserStartup() {
|
||||||
var uriToLoad = null;
|
var uriToLoad = null;
|
||||||
|
|
||||||
// window.arguments[0]: URI to load (string), or an nsISupportsArray of
|
// window.arguments[0]: URI to load (string), or an nsISupportsArray of
|
||||||
// nsISupportsStrings to load
|
// nsISupportsStrings to load, or a xul:tab of
|
||||||
|
// a tabbrowser, which will be replaced by this
|
||||||
|
// window (for this case, all other arguments are
|
||||||
|
// ignored).
|
||||||
// [1]: character set (string)
|
// [1]: character set (string)
|
||||||
// [2]: referrer (nsIURI)
|
// [2]: referrer (nsIURI)
|
||||||
// [3]: postData (nsIInputStream)
|
// [3]: postData (nsIInputStream)
|
||||||
|
@ -880,7 +883,7 @@ function BrowserStartup() {
|
||||||
appCore.startPageCycler();
|
appCore.startPageCycler();
|
||||||
#else
|
#else
|
||||||
# only load url passed in when we're not page cycling
|
# only load url passed in when we're not page cycling
|
||||||
if (uriToLoad && !isLoadingBlank) {
|
if (uriToLoad && !isLoadingBlank) {
|
||||||
if (uriToLoad instanceof Ci.nsISupportsArray) {
|
if (uriToLoad instanceof Ci.nsISupportsArray) {
|
||||||
let count = uriToLoad.Count();
|
let count = uriToLoad.Count();
|
||||||
let specs = [];
|
let specs = [];
|
||||||
|
@ -895,6 +898,17 @@ function BrowserStartup() {
|
||||||
gBrowser.loadTabs(specs, false, true);
|
gBrowser.loadTabs(specs, false, true);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
else if (uriToLoad instanceof XULElement) {
|
||||||
|
// swap the given tab with the default about:blank tab and then close
|
||||||
|
// the original tab in the other window.
|
||||||
|
|
||||||
|
// Stop the about:blank load
|
||||||
|
gBrowser.selectedBrowser.stop();
|
||||||
|
// make sure it has a docshell
|
||||||
|
gBrowser.selectedBrowser.docShell;
|
||||||
|
|
||||||
|
gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, uriToLoad);
|
||||||
|
}
|
||||||
else if (window.arguments.length >= 3) {
|
else if (window.arguments.length >= 3) {
|
||||||
loadURI(uriToLoad, window.arguments[2], window.arguments[3] || null,
|
loadURI(uriToLoad, window.arguments[2], window.arguments[3] || null,
|
||||||
window.arguments[4] || false);
|
window.arguments[4] || false);
|
||||||
|
|
|
@ -271,6 +271,9 @@
|
||||||
</tooltip>
|
</tooltip>
|
||||||
|
|
||||||
<toolbox id="navigator-toolbox" class="toolbox-top" mode="icons"
|
<toolbox id="navigator-toolbox" class="toolbox-top" mode="icons"
|
||||||
|
ondragover="gBrowser._onDragOver(event); event.stopPropagation();"
|
||||||
|
ondrop="gBrowser._onDrop(event); event.stopPropagation();"
|
||||||
|
ondragleave="gBrowser._onDragLeave(event); event.stopPropagation();"
|
||||||
defaultmode="icons">
|
defaultmode="icons">
|
||||||
<!-- Menu -->
|
<!-- Menu -->
|
||||||
<toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
|
<toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
|
||||||
|
|
|
@ -50,6 +50,8 @@
|
||||||
%tabBrowserDTD;
|
%tabBrowserDTD;
|
||||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||||
%globalDTD;
|
%globalDTD;
|
||||||
|
<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
|
||||||
|
%placesDTD;
|
||||||
]>
|
]>
|
||||||
|
|
||||||
<bindings id="tabBrowserBindings"
|
<bindings id="tabBrowserBindings"
|
||||||
|
@ -66,7 +68,10 @@
|
||||||
<xul:stringbundle anonid="tbstringbundle" src="chrome://browser/locale/tabbrowser.properties"/>
|
<xul:stringbundle anonid="tbstringbundle" src="chrome://browser/locale/tabbrowser.properties"/>
|
||||||
<xul:tabbox anonid="tabbox" flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown"
|
<xul:tabbox anonid="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="tab-drop-indicator-bar" collapsed="true" chromedir="&locale.dir;">
|
<xul:hbox class="tab-drop-indicator-bar" collapsed="true" chromedir="&locale.dir;"
|
||||||
|
ondragover="this.parentNode.parentNode._onDragOver(event); event.stopPropagation();"
|
||||||
|
ondragleave="this.parentNode.parentNode._onDragLeave(event); event.stopPropagation();"
|
||||||
|
ondrop="this.parentNode.parentNode._onDrop(event); event.stopPropagation();">
|
||||||
<xul:hbox class="tab-drop-indicator" mousethrough="always"/>
|
<xul:hbox class="tab-drop-indicator" mousethrough="always"/>
|
||||||
</xul:hbox>
|
</xul:hbox>
|
||||||
<xul:hbox class="tabbrowser-strip" collapsed="true" tooltip="_child" context="_child"
|
<xul:hbox class="tabbrowser-strip" collapsed="true" tooltip="_child" context="_child"
|
||||||
|
@ -74,6 +79,7 @@
|
||||||
ondragstart="this.parentNode.parentNode._onDragStart(event); event.stopPropagation();"
|
ondragstart="this.parentNode.parentNode._onDragStart(event); event.stopPropagation();"
|
||||||
ondragover="this.parentNode.parentNode._onDragOver(event); event.stopPropagation();"
|
ondragover="this.parentNode.parentNode._onDragOver(event); event.stopPropagation();"
|
||||||
ondrop="this.parentNode.parentNode._onDrop(event); event.stopPropagation();"
|
ondrop="this.parentNode.parentNode._onDrop(event); event.stopPropagation();"
|
||||||
|
ondragend="this.parentNode.parentNode._onDragEnd(event); event.stopPropagation();"
|
||||||
ondragleave="this.parentNode.parentNode._onDragLeave(event); event.stopPropagation();">
|
ondragleave="this.parentNode.parentNode._onDragLeave(event); event.stopPropagation();">
|
||||||
<xul:tooltip onpopupshowing="return this.parentNode.parentNode.parentNode.createTooltip(event);"/>
|
<xul:tooltip onpopupshowing="return this.parentNode.parentNode.parentNode.createTooltip(event);"/>
|
||||||
<xul:menupopup anonid="tabContextMenu" onpopupshowing="this.parentNode.parentNode.parentNode.updatePopupMenu(this);">
|
<xul:menupopup anonid="tabContextMenu" onpopupshowing="this.parentNode.parentNode.parentNode.updatePopupMenu(this);">
|
||||||
|
@ -92,6 +98,11 @@
|
||||||
oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
|
oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
|
||||||
tabbrowser.removeAllTabsBut(tabbrowser.mContextTab);"/>
|
tabbrowser.removeAllTabsBut(tabbrowser.mContextTab);"/>
|
||||||
<xul:menuseparator/>
|
<xul:menuseparator/>
|
||||||
|
<xul:menuitem id="context_openTabInWindow" label="&cmd.open_window.label;"
|
||||||
|
tbattr="tabbrowser-multiple"
|
||||||
|
oncommand="var tabbrowser = this.parentNode.parentNode.parentNode.parentNode;
|
||||||
|
tabbrowser._replaceTabWithWindow(tabbrowser.mContextTab);"/>
|
||||||
|
<xul:menuseparator/>
|
||||||
<xul:menuitem id="context_bookmarkTab"
|
<xul:menuitem id="context_bookmarkTab"
|
||||||
label="&bookmarkThisTab.label;"
|
label="&bookmarkThisTab.label;"
|
||||||
accesskey="&bookmarkThisTab.accesskey;"
|
accesskey="&bookmarkThisTab.accesskey;"
|
||||||
|
@ -693,10 +704,11 @@
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<method name="updateCurrentBrowser">
|
<method name="updateCurrentBrowser">
|
||||||
|
<parameter name="aForceUpdate"/>
|
||||||
<body>
|
<body>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
var newBrowser = this.getBrowserAtIndex(this.mTabContainer.selectedIndex);
|
var newBrowser = this.getBrowserAtIndex(this.mTabContainer.selectedIndex);
|
||||||
if (this.mCurrentBrowser == newBrowser)
|
if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.mCurrentBrowser) {
|
if (this.mCurrentBrowser) {
|
||||||
|
@ -1609,6 +1621,13 @@
|
||||||
|
|
||||||
ourBrowser.webProgress.addProgressListener(filter,
|
ourBrowser.webProgress.addProgressListener(filter,
|
||||||
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
|
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
|
||||||
|
|
||||||
|
this.setTabTitle(aOurTab);
|
||||||
|
|
||||||
|
// If the tab was already selected (this happpens in the scenraio of
|
||||||
|
// _replaceTabWithWindow), notify onLoactionChange, etc.
|
||||||
|
if (aOurTab == this.selectedTab)
|
||||||
|
this.updateCurrentBrowser(true);
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
@ -1783,17 +1802,12 @@
|
||||||
if (target.localName == "tab" &&
|
if (target.localName == "tab" &&
|
||||||
aEvent.originalTarget.localName != "toolbarbutton") {
|
aEvent.originalTarget.localName != "toolbarbutton") {
|
||||||
var dt = aEvent.dataTransfer;
|
var dt = aEvent.dataTransfer;
|
||||||
dt.mozSetDataAt("application/x-moz-node", target, 0);
|
// We're internetionally not setting any other data-type, otherwise
|
||||||
var URI = this.getBrowserForTab(aEvent.target).currentURI;
|
// applications may override our drop-as-window behavior
|
||||||
if (URI) {
|
dt.mozSetDataAt("application/x-moz-tabbrowser-tab", target, 0);
|
||||||
var spec = URI.spec;
|
|
||||||
dt.mozSetDataAt("text/x-moz-url", spec + "\n" + aEvent.target.label, 0);
|
var canvas = tabPreviews.capture(target, false);
|
||||||
dt.mozSetDataAt("text/uri-list", spec + "\n" + aEvent.target.label, 0);
|
dt.setDragImage(canvas, 0, 0);
|
||||||
dt.mozSetDataAt("text/plain", spec, 0);
|
|
||||||
dt.mozSetDataAt("text/html", '<a href="' + spec + '">' + aEvent.target.label + '</a>', 0);
|
|
||||||
} else {
|
|
||||||
dt.mozSetDataAt("text/plain", "about:blank", 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1806,10 +1820,23 @@
|
||||||
["text/x-moz-url", "text/uri-list", "text/plain", "application/x-moz-file"]
|
["text/x-moz-url", "text/uri-list", "text/plain", "application/x-moz-file"]
|
||||||
]]></field>
|
]]></field>
|
||||||
|
|
||||||
|
<field name="_cachedTargetInToolbox">null</field>
|
||||||
<method name="_setEffectAllowedForDataTransfer">
|
<method name="_setEffectAllowedForDataTransfer">
|
||||||
<parameter name="aEvent"/>
|
<parameter name="aEvent"/>
|
||||||
<body>
|
<body>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
|
// Find out if the we're dragged over the toolbox
|
||||||
|
var target = aEvent.target;
|
||||||
|
var isInToolbox = target == this._cachedTargetInToolbox;
|
||||||
|
while (target && !isInToolbox) {
|
||||||
|
if (target == gNavToolbox) {
|
||||||
|
isInToolbox = true;
|
||||||
|
this._cachedTargetInToolbox = target;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
target = target.parentNode;
|
||||||
|
}
|
||||||
|
|
||||||
var dt = aEvent.dataTransfer;
|
var dt = aEvent.dataTransfer;
|
||||||
// Disallow dropping multiple items
|
// Disallow dropping multiple items
|
||||||
if (dt.mozItemCount > 1)
|
if (dt.mozItemCount > 1)
|
||||||
|
@ -1818,8 +1845,8 @@
|
||||||
var types = dt.mozTypesAt(0);
|
var types = dt.mozTypesAt(0);
|
||||||
var sourceNode = null;
|
var sourceNode = null;
|
||||||
// tabs are always added as the first type
|
// tabs are always added as the first type
|
||||||
if (types[0] == "application/x-moz-node") {
|
if (types[0] == "application/x-moz-tabbrowser-tab") {
|
||||||
var sourceNode = dt.mozGetDataAt("application/x-moz-node", 0);
|
var sourceNode = dt.mozGetDataAt("application/x-moz-tabbrowser-tab", 0);
|
||||||
if (sourceNode instanceof XULElement &&
|
if (sourceNode instanceof XULElement &&
|
||||||
sourceNode.localName == "tab" &&
|
sourceNode.localName == "tab" &&
|
||||||
(sourceNode.parentNode == this.mTabContainer ||
|
(sourceNode.parentNode == this.mTabContainer ||
|
||||||
|
@ -1829,13 +1856,23 @@
|
||||||
(aEvent.screenX >= sourceNode.boxObject.screenX &&
|
(aEvent.screenX >= sourceNode.boxObject.screenX &&
|
||||||
aEvent.screenX <= (sourceNode.boxObject.screenX +
|
aEvent.screenX <= (sourceNode.boxObject.screenX +
|
||||||
sourceNode.boxObject.width))) {
|
sourceNode.boxObject.width))) {
|
||||||
return dt.effectAllowed = "none";
|
return dt.effectAllowed = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Within the toolbox, allow dropping by the height of a tab off
|
||||||
|
// the tabbar
|
||||||
|
if (isInToolbox &&
|
||||||
|
aEvent.screenY < sourceNode.boxObject.screenY -
|
||||||
|
sourceNode.boxObject.height)
|
||||||
|
return dt.effectAllowed = "none";
|
||||||
return dt.effectAllowed = "copyMove";
|
return dt.effectAllowed = "copyMove";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only tab-drags are taken care off within the toolbox
|
||||||
|
if (!isInToolbox)
|
||||||
|
return dt.effectAllowed = "none";
|
||||||
|
|
||||||
for (var i=0; i < this._supportedLinkDropTypes.length; i++) {
|
for (var i=0; i < this._supportedLinkDropTypes.length; i++) {
|
||||||
if (types.contains(this._supportedLinkDropTypes[i])) {
|
if (types.contains(this._supportedLinkDropTypes[i])) {
|
||||||
// Here we need to to do this manually
|
// Here we need to to do this manually
|
||||||
|
@ -1956,12 +1993,15 @@
|
||||||
var dropEffect = dt.dropEffect;
|
var dropEffect = dt.dropEffect;
|
||||||
var draggedTab;
|
var draggedTab;
|
||||||
if (dropEffect != "link") { // copy or move
|
if (dropEffect != "link") { // copy or move
|
||||||
draggedTab = dt.mozGetDataAt("application/x-moz-node", 0);
|
draggedTab = dt.mozGetDataAt("application/x-moz-tabbrowser-tab", 0);
|
||||||
NS_ASSERT(draggedTab && draggedTab.localName == "tab",
|
NS_ASSERT(draggedTab && draggedTab.localName == "tab",
|
||||||
"copy or move action without a tab");
|
"copy or move action without a tab");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (draggedTab && (dropEffect == "copy" || draggedTab.parentNode == this.mTabContainer)) {
|
this.mTabDropIndicatorBar.collapsed = true;
|
||||||
|
|
||||||
|
if (draggedTab && (dropEffect == "copy" ||
|
||||||
|
draggedTab.parentNode == this.mTabContainer)) {
|
||||||
var newIndex = this.getNewIndex(aEvent);
|
var newIndex = this.getNewIndex(aEvent);
|
||||||
if (dropEffect == "copy") {
|
if (dropEffect == "copy") {
|
||||||
// copy the dropped tab (wherever it's from)
|
// copy the dropped tab (wherever it's from)
|
||||||
|
@ -1998,7 +2038,6 @@
|
||||||
// swapBrowsersAndCloseOther, so that the updateCurrentBrowser
|
// swapBrowsersAndCloseOther, so that the updateCurrentBrowser
|
||||||
// it triggers will correctly update our URL bar.
|
// it triggers will correctly update our URL bar.
|
||||||
this.selectedTab = newTab;
|
this.selectedTab = newTab;
|
||||||
this.setTabTitle(newTab);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var url;
|
var url;
|
||||||
|
@ -2060,20 +2099,51 @@
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
<method name="_onDragEnd">
|
||||||
|
<parameter name="aEvent"/>
|
||||||
|
<body>
|
||||||
|
<![CDATA[
|
||||||
|
if (this.mTabs.length == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var dt = aEvent.dataTransfer;
|
||||||
|
if (dt.dropEffect == "none") {
|
||||||
|
var draggedTab = dt.mozGetDataAt("application/x-moz-tabbrowser-tab", 0);
|
||||||
|
this._replaceTabWithWindow(draggedTab);
|
||||||
|
}
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="_replaceTabWithWindow">
|
||||||
|
<parameter name="aTab"/>
|
||||||
|
<body>
|
||||||
|
<![CDATA[
|
||||||
|
// tell a new window to take the "dropped" tab
|
||||||
|
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||||
|
getService(Ci.nsIWindowWatcher);
|
||||||
|
ww.openWindow(window,
|
||||||
|
getBrowserURL(),
|
||||||
|
null,
|
||||||
|
"chrome,dialog=no,all",
|
||||||
|
aTab);
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
|
|
||||||
<method name="_onDragLeave">
|
<method name="_onDragLeave">
|
||||||
<parameter name="aEvent"/>
|
<parameter name="aEvent"/>
|
||||||
<body>
|
<body>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
this.mDragTime = 0;
|
this.mDragTime = 0;
|
||||||
|
|
||||||
var dropEffect = aEvent.dataTransfer.dropEffect;
|
// This does not work at all (see bug 458613)
|
||||||
if (dropEffect == "move" || dropEffect == "copy") {
|
var target = aEvent.relatedTarget;
|
||||||
var target = aEvent.relatedTarget;
|
while (target && (target != this && target != gNavToolbox))
|
||||||
while (target && target != this.mStrip)
|
target = target.parentNode;
|
||||||
target = target.parentNode;
|
if (target)
|
||||||
if (target)
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.mTabDropIndicatorBar.collapsed = true;
|
this.mTabDropIndicatorBar.collapsed = true;
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1032,6 +1032,7 @@
|
||||||
var ip = this.insertionPoint;
|
var ip = this.insertionPoint;
|
||||||
if (!ip || !PlacesControllerDragHelper.canDrop(ip)) {
|
if (!ip || !PlacesControllerDragHelper.canDrop(ip)) {
|
||||||
ib.removeAttribute("dragging");
|
ib.removeAttribute("dragging");
|
||||||
|
PlacesControllerDragHelper.currentDataTransfer = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1103,8 +1104,10 @@
|
||||||
]]></handler>
|
]]></handler>
|
||||||
|
|
||||||
<handler event="drop"><![CDATA[
|
<handler event="drop"><![CDATA[
|
||||||
// Cache the dataTransfer
|
// If the data-transfer isn't cached, it's not ours
|
||||||
PlacesControllerDragHelper.currentDataTransfer = event.dataTransfer;
|
// This happens when dropping tabs
|
||||||
|
if (event.dataTransfer != PlacesControllerDragHelper.currentDataTransfer)
|
||||||
|
return;
|
||||||
|
|
||||||
var dropPoint = this._getDropPoint(event);
|
var dropPoint = this._getDropPoint(event);
|
||||||
if (!dropPoint)
|
if (!dropPoint)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче