How to programmatically move a tab to another window in the Firefox add-on SDK extension?

Although it looks like you can change the order of the tabs in the window by updating the tab .index property, it does not look like api tabs . directly supports moving a tab to another window.

Am I missing something? Is there a viable workaround?

+5
source share
3 answers

This is possible through the low-level window/utils module. The example below duplicates the active tab in each open window

 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 }); } }); ; base64, iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8 / 9hAAACUElEQVQ4jaWTTWtTURCGjzc33CCpbVKN4kexC9EUY1Hov + iqPyDrbgtuCrViKUERqsWVguBGQaW4UiKiaEVxoShFGgnuBMUqNW3zce49Z + ZxUWtwoRR8YXbzPswM7xj + JgVEiXGsYVknxgII4Ltt5p8AB8RArOAUVQfqQJNtAFA8QgvF6i9PR1Dt0KbVBTjncM4hIni / OZv3HsRB + wvefiP2LcQnJIkQe49FEJFNQLPZZHh4mEwmQyqVoqenh3K5TGvlK1dOlageH + HG4DFar1 / S0A6Lr99xdN8QxWKRXC6HGR0dJZvNMjk5Sb1ep1gskk6nuTo / D + / ec7dvkBdhP9cKeX7UXxEZQ2 / YRxRFLC8vY + bm5qhUKnjvsdYyPj5OFEWcnTnHujiS5TfcPDbAw50h9w7u5f7UadLZFLVaDRHBiGzuY61lbGyMXC5HoVBgrbGGWAW / TvvxHR7s7udFKs / 1oyfZ + PSRTqeDqm7eoFqtEoYhmUyG2dlZVJU4iREfI / WP3Nt9iMUdu7jdf5Anly5i0oaVlRWazSZmYWGBIAiIoohyucz09DQTExPMnJli9dlT5vcM8Kh3gFsHDuNqb9mb7yXMRBhjWFpawpRKJVKpFMYYgiAgDEOCIOD81BkunBjh8pEhKqUhGkvP6bQ / U // wgUP5 / 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 }); } }); , 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 }); } }); 
+2
source

I got inspiration from @Noitidart's answer and came up with my solution.

I am adding the setWindow(window, index) method to the Tab prototype, so that any SDK tab can be moved to another window from anywhere in the addon using a simple call like this:

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

This will lead to the active active tab of window 0 at the beginning of the active window.

And here is the method:

Update:

I put together a module to do just that: jetpack-tab-setwindow


Old solution (breaks in 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); } }; 
+3
source
Decision

@paa is nice, but it doesn't move the tab. It is duplicated by a tab. Thus, flash movies do not retain their position, etc. And this is not the movement of his duplication, as he explained.

I did a lot of research, it was fun. The way tabs are moved in Firefox is through the exchange of docShell. This will accomplish what you want. This is written for bootstrap, although so you need to tweak it for addon sdk.

Pass the second argument as a tabbed or non-tabbed string if you want to move it to a new window. Else passes the second argument to the existing window, and it will be moved there. can copy paste and run this code from the satch panel.

function gBrowser.swapBrowsersAndCloseOther is 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
source

Source: https://habr.com/ru/post/1204291/


All Articles