mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-25 11:15:34 +00:00
Bug 1458056 - Implement ability to move a selection of tabs into another window through drag and drop. r=jaws
MozReview-Commit-ID: LFFoE6HsBp8 Differential Revision: https://phabricator.services.mozilla.com/D2986 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
584157b2d3
commit
19bf2f8d32
@ -3487,6 +3487,12 @@ window._gBrowser = {
|
||||
if (activeTabNewIndex > -1) {
|
||||
win.gBrowser.adoptTab(activeTab, activeTabNewIndex, true /* aSelectTab */);
|
||||
}
|
||||
|
||||
// Restore tab selection
|
||||
let winVisibleTabs = win.gBrowser.visibleTabs;
|
||||
let winTabLength = winVisibleTabs.length;
|
||||
win.gBrowser.addRangeToMultiSelectedTabs(winVisibleTabs[0],
|
||||
winVisibleTabs[winTabLength - 1]);
|
||||
}, { once: true });
|
||||
|
||||
win = this.replaceTabWithWindow(firstInactiveTab);
|
||||
|
@ -1479,7 +1479,14 @@
|
||||
}
|
||||
} else if (draggedTab) {
|
||||
let newIndex = this._getDropIndex(event, false);
|
||||
gBrowser.adoptTab(draggedTab, newIndex, true);
|
||||
let newTabs = [];
|
||||
for (let tab of movingTabs) {
|
||||
let newTab = gBrowser.adoptTab(tab, newIndex++, tab == draggedTab);
|
||||
newTabs.push(newTab);
|
||||
}
|
||||
|
||||
// Restore tab selection
|
||||
gBrowser.addRangeToMultiSelectedTabs(newTabs[0], newTabs[newTabs.length - 1]);
|
||||
} else {
|
||||
// Pass true to disallow dropping javascript: or data: urls
|
||||
let links;
|
||||
@ -1606,7 +1613,7 @@
|
||||
props.outerWidth = winWidth;
|
||||
props.outerHeight = winHeight;
|
||||
}
|
||||
gBrowser.replaceTabWithWindow(draggedTab, props);
|
||||
gBrowser.replaceTabsWithWindow(draggedTab, props);
|
||||
}
|
||||
event.stopPropagation();
|
||||
]]></handler>
|
||||
|
@ -28,6 +28,7 @@ support-files =
|
||||
[browser_multiselect_tabs_close.js]
|
||||
[browser_multiselect_tabs_copy_through_drag_and_drop.js]
|
||||
[browser_multiselect_tabs_event.js]
|
||||
[browser_multiselect_tabs_move_to_another_window_drag.js]
|
||||
[browser_multiselect_tabs_move_to_new_window_contextmenu.js]
|
||||
[browser_multiselect_tabs_mute_unmute.js]
|
||||
[browser_multiselect_tabs_pin_unpin.js]
|
||||
|
@ -1,7 +1,4 @@
|
||||
const PREF_MULTISELECT_TABS = "browser.tabs.multiselect";
|
||||
function url(tab) {
|
||||
return tab.linkedBrowser.currentURI.spec;
|
||||
}
|
||||
|
||||
add_task(async function setPref() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
@ -48,8 +45,8 @@ add_task(async function test() {
|
||||
ok(!tabs[i].multiselected, "Tab" + i + " is not multiselected");
|
||||
}
|
||||
|
||||
await BrowserTestUtils.waitForCondition(() => url(tab4) == url(tab1));
|
||||
await BrowserTestUtils.waitForCondition(() => url(tab5) == url(tab2));
|
||||
await BrowserTestUtils.waitForCondition(() => getUrl(tab4) == getUrl(tab1));
|
||||
await BrowserTestUtils.waitForCondition(() => getUrl(tab5) == getUrl(tab2));
|
||||
|
||||
ok(true, "Tab1 and tab2 are duplicated succesfully");
|
||||
|
||||
|
@ -0,0 +1,71 @@
|
||||
const PREF_MULTISELECT_TABS = "browser.tabs.multiselect";
|
||||
const PREF_ANIMATIONS_ENABLED = "toolkit.cosmeticAnimations.enabled";
|
||||
|
||||
add_task(async function setPref() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[PREF_MULTISELECT_TABS, true],
|
||||
[PREF_ANIMATIONS_ENABLED, false]
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test() {
|
||||
let tab1 = await addTab();
|
||||
let tab2 = await addTab();
|
||||
let tab3 = await addTab("http://mochi.test:8888/3");
|
||||
let tab4 = await addTab();
|
||||
let tab5 = await addTab("http://mochi.test:8888/5");
|
||||
|
||||
is(gBrowser.multiSelectedTabsCount, 0, "Zero multiselected tabs");
|
||||
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab2);
|
||||
await triggerClickOn(tab1, { ctrlKey: true });
|
||||
|
||||
ok(tab1.multiselected, "Tab1 is multiselected");
|
||||
ok(tab2.multiselected, "Tab2 is multiselected");
|
||||
ok(!tab3.multiselected, "Tab3 is not multiselected");
|
||||
ok(!tab4.multiselected, "Tab4 is not multiselected");
|
||||
ok(!tab5.multiselected, "Tab5 is not multiselected");
|
||||
is(gBrowser.multiSelectedTabsCount, 2, "Two multiselected tabs");
|
||||
|
||||
let newWindow = gBrowser.replaceTabsWithWindow(tab1);
|
||||
|
||||
// waiting for tab2 to close ensure that the newWindow is created,
|
||||
// thus newWindow.gBrowser used in the second waitForCondition
|
||||
// will not be undefined.
|
||||
await TestUtils.waitForCondition(() => tab2.closing, "Wait for tab2 to close");
|
||||
await TestUtils.waitForCondition(() => newWindow.gBrowser.visibleTabs.length == 2,
|
||||
"Wait for all two tabs to get moved to the new window");
|
||||
|
||||
let gBrowser2 = newWindow.gBrowser;
|
||||
tab1 = gBrowser2.visibleTabs[0];
|
||||
tab2 = gBrowser2.visibleTabs[1];
|
||||
|
||||
if (gBrowser.selectedTab != tab3)
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab3);
|
||||
|
||||
await triggerClickOn(tab5, { ctrlKey: true });
|
||||
|
||||
ok(tab1.multiselected, "Tab1 is multiselected");
|
||||
ok(tab2.multiselected, "Tab2 is multiselected");
|
||||
ok(tab3.multiselected, "Tab3 is multiselected");
|
||||
ok(!tab4.multiselected, "Tab4 is not multiselected");
|
||||
ok(tab5.multiselected, "Tab5 is multiselected");
|
||||
|
||||
await dragAndDrop(tab3, tab1, false, newWindow);
|
||||
|
||||
await TestUtils.waitForCondition(() => gBrowser2.visibleTabs.length == 4,
|
||||
"Moved tab3 and tab5 to second window");
|
||||
|
||||
tab3 = gBrowser2.visibleTabs[1];
|
||||
tab5 = gBrowser2.visibleTabs[2];
|
||||
|
||||
await BrowserTestUtils.waitForCondition(() => getUrl(tab3) == "http://mochi.test:8888/3");
|
||||
await BrowserTestUtils.waitForCondition(() => getUrl(tab5) == "http://mochi.test:8888/5");
|
||||
|
||||
ok(true, "Tab3 and tab5 are duplicated succesfully");
|
||||
|
||||
BrowserTestUtils.closeWindow(newWindow);
|
||||
BrowserTestUtils.removeTab(tab4);
|
||||
});
|
@ -157,7 +157,7 @@ async function test_mute_tab(tab, icon, expectMuted) {
|
||||
return mutedPromise;
|
||||
}
|
||||
|
||||
async function dragAndDrop(tab1, tab2, copy) {
|
||||
async function dragAndDrop(tab1, tab2, copy, destWindow = window) {
|
||||
let rect = tab2.getBoundingClientRect();
|
||||
let event = {
|
||||
ctrlKey: copy,
|
||||
@ -166,10 +166,23 @@ async function dragAndDrop(tab1, tab2, copy) {
|
||||
clientY: rect.top + rect.height / 2,
|
||||
};
|
||||
|
||||
if (destWindow != window) {
|
||||
// Make sure that both tab1 and tab2 are visible
|
||||
window.focus();
|
||||
window.moveTo(rect.left, rect.top + rect.height * 3);
|
||||
}
|
||||
|
||||
let originalTPos = tab1._tPos;
|
||||
EventUtils.synthesizeDrop(tab1, tab2, null, copy ? "copy" : "move", window, window, event);
|
||||
if (!copy) {
|
||||
EventUtils.synthesizeDrop(tab1, tab2, null, copy ? "copy" : "move", window, destWindow, event);
|
||||
if (!copy && destWindow == window) {
|
||||
await BrowserTestUtils.waitForCondition(() => tab1._tPos != originalTPos,
|
||||
"Waiting for tab position to be updated");
|
||||
} else if (destWindow != window) {
|
||||
await BrowserTestUtils.waitForCondition(() => tab1.closing,
|
||||
"Waiting for tab closing");
|
||||
}
|
||||
}
|
||||
|
||||
function getUrl(tab) {
|
||||
return tab.linkedBrowser.currentURI.spec;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user