Bug 1480907 - Implement ability to bookmark a selection of tabs through drag and drop. r=Felipe

Differential Revision: https://phabricator.services.mozilla.com/D4589

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jared Wein 2018-09-05 14:16:59 +00:00
Родитель e638e46d0b
Коммит d7a8b85f4c
3 изменённых файлов: 104 добавлений и 29 удалений

Просмотреть файл

@ -826,28 +826,35 @@
<parameter name="event"/>
<body><![CDATA[
var dt = event.dataTransfer;
if (dt.mozItemCount == 1) {
var types = dt.mozTypesAt(0);
let isMovingTabs = dt.mozItemCount > 0;
for (let i = 0; i < dt.mozItemCount; i++) {
// tabs are always added as the first type
if (types[0] == TAB_DROP_TYPE) {
let sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
if (sourceNode instanceof XULElement &&
sourceNode.localName == "tab" &&
sourceNode.ownerGlobal.isChromeWindow &&
sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser" &&
sourceNode.ownerGlobal.gBrowser.tabContainer == sourceNode.parentNode) {
// Do not allow transfering a private tab to a non-private window
// and vice versa.
if (PrivateBrowsingUtils.isWindowPrivate(window) !=
PrivateBrowsingUtils.isWindowPrivate(sourceNode.ownerGlobal))
return "none";
let types = dt.mozTypesAt(0);
if (types[0] != TAB_DROP_TYPE) {
isMovingTabs = false;
break;
}
}
if (window.gMultiProcessBrowser !=
sourceNode.ownerGlobal.gMultiProcessBrowser)
return "none";
if (isMovingTabs) {
let sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
if (sourceNode instanceof XULElement &&
sourceNode.localName == "tab" &&
sourceNode.ownerGlobal.isChromeWindow &&
sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser" &&
sourceNode.ownerGlobal.gBrowser.tabContainer == sourceNode.parentNode) {
// Do not allow transfering a private tab to a non-private window
// and vice versa.
if (PrivateBrowsingUtils.isWindowPrivate(window) !=
PrivateBrowsingUtils.isWindowPrivate(sourceNode.ownerGlobal))
return "none";
return dt.dropEffect == "copy" ? "copy" : "move";
}
if (window.gMultiProcessBrowser !=
sourceNode.ownerGlobal.gMultiProcessBrowser)
return "none";
return dt.dropEffect == "copy" ? "copy" : "move";
}
}
@ -1199,14 +1206,22 @@
if (!tab || this._isCustomizing)
return;
let dt = event.dataTransfer;
dt.mozSetDataAt(TAB_DROP_TYPE, tab, 0);
let browser = tab.linkedBrowser;
let selectedTabs = gBrowser.selectedTabs;
let otherSelectedTabs = selectedTabs.filter(selectedTab => selectedTab != tab);
let dataTransferOrderedTabs = [tab].concat(otherSelectedTabs);
// We must not set text/x-moz-url or text/plain data here,
// otherwise trying to deatch the tab by dropping it on the desktop
// may result in an "internet shortcut"
dt.mozSetDataAt("text/x-moz-text-internal", browser.currentURI.spec, 0);
let dt = event.dataTransfer;
for (let i = 0; i < dataTransferOrderedTabs.length; i++) {
let dtTab = dataTransferOrderedTabs[i];
dt.mozSetDataAt(TAB_DROP_TYPE, dtTab, i);
let dtBrowser = dtTab.linkedBrowser;
// We must not set text/x-moz-url or text/plain data here,
// otherwise trying to detach the tab by dropping it on the desktop
// may result in an "internet shortcut"
dt.mozSetDataAt("text/x-moz-text-internal", dtBrowser.currentURI.spec, i);
}
// Set the cursor to an arrow during tab drags.
dt.mozCursor = "default";
@ -1215,10 +1230,9 @@
// node to deliver the `dragend` event. See bug 1345473.
dt.addElement(tab);
// Regroup all selected tabs around the dragged tab
// for multiple tabs dragging
if (tab.multiselected) {
let selectedTabs = gBrowser.selectedTabs;
// Regroup all selected tabs around the dragged tab
// for multiple tabs dragging
let draggedTabPos = tab._tPos;
// Move left selected tabs
@ -1257,6 +1271,7 @@
canvas.height = 90 * scale;
let toDrag = canvas;
let dragImageOffset = -16;
let browser = tab.linkedBrowser;
if (gMultiProcessBrowser) {
var context = canvas.getContext("2d");
context.fillStyle = "white";

Просмотреть файл

@ -27,6 +27,7 @@ support-files =
[browser_multiselect_tabs_close_using_shortcuts.js]
[browser_multiselect_tabs_close.js]
[browser_multiselect_tabs_copy_through_drag_and_drop.js]
[browser_multiselect_tabs_drag_to_bookmarks_toolbar.js]
[browser_multiselect_tabs_duplicate.js]
[browser_multiselect_tabs_event.js]
[browser_multiselect_tabs_move_to_another_window_drag.js]

Просмотреть файл

@ -0,0 +1,59 @@
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() {
// Open Bookmarks Toolbar
let bookmarksToolbar = document.getElementById("PersonalToolbar");
setToolbarVisibility(bookmarksToolbar, true);
ok(!bookmarksToolbar.collapsed, "bookmarksToolbar should be visible now");
let tab1 = await addTab("http://mochi.test:8888/1");
let tab2 = await addTab("http://mochi.test:8888/2");
let tab3 = await addTab("http://mochi.test:8888/3");
let tab4 = await addTab("http://mochi.test:8888/4");
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");
// Use getElementsByClassName so the list is live and will update as items change.
let currentBookmarks = bookmarksToolbar.getElementsByClassName("bookmark-item");
let startBookmarksLength = currentBookmarks.length;
let lastBookmark = currentBookmarks[currentBookmarks.length - 1];
await EventUtils.synthesizePlainDragAndDrop({srcElement: tab1, destElement: lastBookmark});
await TestUtils.waitForCondition(() => currentBookmarks.length == startBookmarksLength + 2,
"waiting for 2 bookmarks");
is(currentBookmarks.length, startBookmarksLength + 2, "Bookmark count should have increased by 2");
// Drag non-selection to the bookmarks toolbar
startBookmarksLength = currentBookmarks.length;
await EventUtils.synthesizePlainDragAndDrop({srcElement: tab3, destElement: lastBookmark});
await TestUtils.waitForCondition(() => currentBookmarks.length == startBookmarksLength + 1,
"waiting for 1 bookmark");
is(currentBookmarks.length, startBookmarksLength + 1, "Bookmark count should have increased by 1");
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
BrowserTestUtils.removeTab(tab3);
BrowserTestUtils.removeTab(tab4);
BrowserTestUtils.removeTab(tab5);
});