如何在firefox插件SDK扩展中以编程方式将选项卡移动到另一个窗口?

如何在firefox插件SDK扩展中以编程方式将选项卡移动到另一个窗口?,firefox,firefox-addon,firefox-addon-sdk,Firefox,Firefox Addon,Firefox Addon Sdk,虽然看起来您可以通过更新tab.index属性来更改窗口中选项卡的顺序,但它似乎不直接支持将选项卡移动到另一个窗口 我错过什么了吗?是否有可行的解决方法?可以通过低级模块窗口/utils。下面的示例在每个打开的窗口中复制活动选项卡 const{getMostRecentBrowserWindow,windows:getWindows}=require(“sdk/window/utils”); const{ActionButton}=require(“sdk/ui/button/action”);

虽然看起来您可以通过更新tab
.index
属性来更改窗口中选项卡的顺序,但它似乎不直接支持将选项卡移动到另一个窗口


我错过什么了吗?是否有可行的解决方法?

可以通过低级模块
窗口/utils
。下面的示例在每个打开的窗口中复制活动选项卡

const{getMostRecentBrowserWindow,windows:getWindows}=require(“sdk/window/utils”);
const{ActionButton}=require(“sdk/ui/button/action”);
var按钮=动作按钮({
id:“重复选项卡按钮”,
标签:“重复标签”,
偶像:"数据:图像/png;Bas64,IBoBoWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeWeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4dfar1/6月6日,中国政府发布了一份关于某一方面的研究报告,并对其进行了研究。6月8日,中国政府发布了一份关于某一方面的研究,并对其进行了研究。8月8日,中国政府发布了一份关于该领域的研究报告。6月6日,该研究的研究结果是一份关于该领域的研究。6月6日,中国政府发布了一份关于该领域的一份研究的研究成果。6月8月8月8日,中国政府对一份关于该领域的非非非政府部门的一份研究的非非非政府部门的非非非非政府部门的非政府部门的非政府部门的非非政府部门的非政府部门的非政府非政府部门的非政府部门的非政府非政府部门的非政府部门的非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非政府非MB7YXMRBHJWFPAWPRKJVKPFMYYGIAGDEOCIOD81BkunBjh8pEhKqUhGkvP6bQ/U//wgUP5/YRHSDABXBTBVQV5XYQ2Q0KGR8NDOM7JKUO/Y5QGGQIDPVMLNKQCKCQUJFSORXEHAJXA48EFU6XV4EQOPv4EMQTN7RBSS7WL+/GVB038DFGJNYUABBHZUBQAABJRU5ERKJGG=”,
onClick:function(){
var xulwindows=getWindows(“导航器:浏览器”);
var xulactivewindow=getMostRecentBrowserWindow();
var xulactivetab=xulactivewindow.gBrowser.selectedTab;
forEach(函数(win){
如果(win==XULACTIVE窗口)
返回;
var duplicatedtab=win.gBrowser.duplicateTab(xulactivetab);
win.gBrowser.moveTabTo(duplicatedtab,0);//第二个参数是索引
});
}
});

@paa的解决方案很好,但它不会移动标签。他正在复制标签。因此flash电影不会保留其位置等。正如他解释的,这不是移动,而是复制

我做了很多研究,真的很有趣。他们在Firefox中移动标签的方式是通过docShell交换。这将实现你想要的。它是为引导编写的,不过需要修改插件sdk

如果要将第二个参数移动到新窗口,请将其作为
选项卡式
非选项卡式
的字符串传递。否则,将第二个参数传递到现有窗口,它将被移动到该窗口。可以从sratchpad复制粘贴并运行此代码

这将使用
gBrowser.swapbrowser和closeother
函数

function moveTabToWin(aTab, tDOMWin) {
  //tDOMWin means target DOMWindow means the window you want the tab in
  //if tDOMWin == 'tabbed' or == 'non-tabbed' it opens in a new window
  //if aTopContWin is the last in its window, then its window is closed
  if (tDOMWin == 'tabbed' || tDOMWin == 'non-tabbed') {
    var sa = Cc["@mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
    var wuri = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
    wuri.data = 'about:blank';
    sa.AppendElement(wuri);
    let features = "chrome,dialog=no";
    if (tDOMWin == 'tabbed') {
      features += ',all';
    }
    var sDOMWin = aTab.ownerGlobal; //source DOMWindow
    if (PrivateBrowsingUtils.permanentPrivateBrowsing || PrivateBrowsingUtils.isWindowPrivate(sDOMWin)) {
       features += ",private";
    } else {
       features += ",non-private";
    }
    var XULWindow = Services.ww.openWindow(null, 'chrome://browser/content/browser.xul', null, features, sa);
    XULWindow.addEventListener('load', function() {
      var DOMWindow = XULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
      DOMWindow.gBrowser.selectedTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
      DOMWindow.gBrowser.swapBrowsersAndCloseOther(DOMWindow.gBrowser.selectedTab, aTab);
      //DOMWindow.gBrowser.selectedTab = newTab;
    }, false);
  } else if (tDOMWin) {
    //existing dom window
    var newTab = tDOMWin.gBrowser.addTab('about:blank');
    newTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
    tDOMWin.gBrowser.swapBrowsersAndCloseOther(newTab, aTab);
    tDOMWin.gBrowser.selectedTab = newTab;
  }
}

moveTabToWin(gBrowser.selectedTab, 'tabbed');

我从@Noitidart的答案中得到启发,并提出了我的解决方案

我正在将
setWindow(window,index)
方法添加到
Tab
的原型中,这样任何SDK选项卡都可以通过如下简单调用从插件中的任何位置移动到另一个窗口:

browserWindows[0].activeTab.setWindow(browserWindows.activeWindow, 0);
这会将窗口0的活动选项卡移动到活动窗口的开头

方法如下:

更新:

我创建了一个模块来实现这一点:


旧解决方案(FF43中断)

var Tab=require(“sdk/tabs/Tab”).Tab;
Tab.prototype.setWindow=函数(窗口,索引){
var tab=这个;
var oldWindow=tab.window;
如果(旧窗口!==窗口){
//我们必须在这里使用较低级别的API
var Ci=要求('chrome').Ci;
var viewFor=require(“sdk/view/core”).viewFor;
var aTab=视图(选项卡);
var aWin=视图(窗口);
var gBrowser=aWin.gBrowser;
//获取选项卡属性
var isSelected=oldWindow.activeTab==tab;
var isPinned=aTab.pinned;
//调试日志:
var tabId=tab.id;
log('setWindow',{index,isSelected,isPinned,tab,tabId});
//在目标窗口上创建占位符选项卡
var newTab=gBrowser.addTab('about:newTab');
newTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.stop_ALL);//我们无论如何都不需要这个选项卡
//如果指定了索引,请将占位符选项卡移动到所需索引
如果(索引!=未定义){
var length=gBrowser.tabContainer.childElementCount;
如果(指数<0)指数=长度-指数;

如果(0)真棒的问题Hans!复制是真正的移动方式吗?如果你在选项卡中播放视频并复制该选项卡,那么如果你复制它,它将不再播放视频。它复制选项卡状态,这不包括完整的内容窗口状态。嘿,paa,伙计,我们应该进行docshell交换,对吗?这样会更好ves的东西。你知道如何进行docShell交换吗?我正在尝试学习。显然,这就是firefox将选项卡移动到新窗口的方式。@Noitidart
duplicateTab
是firefox的操作方式。哇,非常好@Duzun!感谢分享!一位用户询问如何在SDK中进行此操作,您的解决方案比我的更适合他-感谢您提供的原始解决方案@Noitidart!我的解决方案丢失了一些东西,从FF 43-44开始,我得到了一个奇怪的错误,没有任何细节(堆栈、文件、描述-无)。我想这是因为我正在访问新的标签或其他东西…有时我会出现一个空白窗口(没有标签)这还没有结束。感谢您分享这一症状,希望有人能解决这一问题。:)我看到@kousu在使用
replaceTabWithWindow()
时找到了将选项卡移动到新窗口的更好解决方案。我无法登录到那里发表评论,授权系统中出现了一些问题:-(他的解决方案似乎不适用于移动到现有窗口,但我相信应该有一个比我在
setWindow()
中使用的更好的解决方案,用于将选项卡移动到不同窗口的一般问题。我将
var Tab = require("sdk/tabs/tab").Tab;

Tab.prototype.setWindow = function (window, index) {
    var tab = this;
    var oldWindow = tab.window;
    if ( oldWindow !== window ) {
        // We have to use lower-level API here
        var Ci      = require('chrome').Ci;
        var viewFor = require("sdk/view/core").viewFor;

        var aTab = viewFor(tab);
        var aWin = viewFor(window);
        var gBrowser = aWin.gBrowser;

        // Get tab properties
        var isSelected = oldWindow.activeTab == tab;
        var isPinned   = aTab.pinned;

        // Log for debugging:
        var tabId = tab.id;
        console.log('setWindow', {index, isSelected, isPinned, tab, tabId});

        // Create a placeholder-tab on destination windows
        var newTab = gBrowser.addTab('about:newtab');
        newTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL); // we don't need this tab anyways

        // If index specified, move placeholder-tab to desired index
        if ( index != undefined ) {
            var length = gBrowser.tabContainer.childElementCount;
            if ( index < 0 ) index = length - index;
            if( 0 <= index && index < length ) {
                gBrowser.moveTabTo(newTab, index);
            }
        }
        // Copy tab properties to placeholder-tab
        if ( isPinned ) {
            gBrowser.pinTab(newTab);
        }

        // For some reason this doesn't seem to work :-(
        if ( isSelected ) {
            gBrowser.selectedTab = newTab;
        }

        // Swap tabs and remove placeholder-tab
        gBrowser.swapBrowsersAndCloseOther(newTab, aTab);
    }
};