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

时间:2014-10-09 00:01:39

标签: firefox firefox-addon firefox-addon-sdk

虽然看起来您可以通过更新标签.index属性来更改窗口中标签的顺序,但它看起来不像tabs api直接支持将标签移动到另一个窗口。

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

3 个答案:

答案 0 :(得分:2)

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

const { getMostRecentBrowserWindow, windows: getWindows } = require("sdk/window/utils");

const { ActionButton } = require("sdk/ui/button/action");

var button = ActionButton({
  id: "duplicatetab-button",
  label: "Duplicate tab",
  icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACUElEQVQ4jaWTTWtTURCGjzc33CCpbVKN4kexC9EUY1Hov+iqPyDrbgtuCrViKUERqsWVguBGQaW4UiKiaEVxoShFGgnuBMUqNW3zce49Z+ZxUWtwoRR8YXbzPswM7xj+JgVEiXGsYVknxgII4Ltt5p8AB8RArOAUVQfqQJNtAFA8QgvF6i9PR1Dt0KbVBTjncM4hIni/OZv3HsRB+wvefiP2LcQnJIkQe49FEJFNQLPZZHh4mEwmQyqVoqenh3K5TGvlK1dOlageH+HG4DFar1/S0A6Lr99xdN8QxWKRXC6HGR0dJZvNMjk5Sb1ep1gskk6nuTo/D+/ec7dvkBdhP9cKeX7UXxEZQ2/YRxRFLC8vY+bm5qhUKnjvsdYyPj5OFEWcnTnHujiS5TfcPDbAw50h9w7u5f7UadLZFLVaDRHBiGzuY61lbGyMXC5HoVBgrbGGWAW/TvvxHR7s7udFKs/1oyfZ+PSRTqeDqm7eoFqtEoYhmUyG2dlZVJU4iREfI/WP3Nt9iMUdu7jdf5Anly5i0oaVlRWazSZmYWGBIAiIoohyucz09DQTExPMnJli9dlT5vcM8Kh3gFsHDuNqb9mb7yXMRBhjWFpawpRKJVKpFMYYgiAgDEOCIOD81BkunBjh8pEhKqUhGkvP6bQ/U//wgUP5/YRhSDabxbTbbVQV5xyq2q0kgR8NdOM7JKuo/Y5qggqIdPvMlnkrQCKCquJFsOrxeHAJxA48eFU6Xv4EqOpv41YqnQirqliv4MEmQtN7RBSs7wL+/gvb038DfgJnyUabbHzUbQAAAABJRU5ErkJggg==",
  onClick: function() {
    var xulwindows = getWindows("navigator:browser");
    var xulactivewindow = getMostRecentBrowserWindow();
    var xulactivetab = xulactivewindow.gBrowser.selectedTab;

    xulwindows.forEach(function(win){
      if(win === xulactivewindow)
        return;
      var duplicatedtab = win.gBrowser.duplicateTab(xulactivetab);
      win.gBrowser.moveTabTo(duplicatedtab, 0); // the second argument is the index
    });
  }
});

答案 1 :(得分:2)

@ paa的解决方案很不错,但它没有移动标签。他正在复制标签。因此,闪光电影不会保留他们的位置等。而且这不是一个重复,就像他解释的那样。

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

如果要将第二个参数移动到新窗口,请将其作为tabbednon-tabbed的字符串传递。否则将第二个参数传递给现有窗口,它将被移动到那里。可以复制粘贴并从sratchpad运行此代码。

这使用gBrowser.swapBrowsersAndCloseOther函数

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');

答案 2 :(得分:2)

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

我已将setWindow(window, index)方法添加到Tab的原型中,因此任何SDK标签都可以通过简单的调用从插件的任何位置移动到另一个窗口:

browserWindows[0].activeTab.setWindow(browserWindows.activeWindow, 0);

这会将窗口0的活动标签移动到活动窗口的开头。

以下是方法:

<强>更新

我已经整理了一个模块来完成这项工作:jetpack-tab-setwindow

旧解决方案(在FF43中断)

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);
    }
};