mirror of
https://github.com/zen-browser/desktop.git
synced 2025-12-31 02:32:15 +00:00
chore: Drag and drop refactor, p=#11723
* feat: Full cross-window workspace syncing, b=no-bug, c=workspaces * feat: Also change icons and labels if the tab is pending, b=no-bug, c=tabs, workspaces * feat: Dont session duplicate the tabs, b=no-bug, c=workspaces * feat: Properly handle tab moves, b=no-bug, c=workspaces * feat: Start on new session restore, b=no-bug, c=no-component * Discard changes to prefs/browser.yaml * feat: Start doing out own session restore, b=no-bug, c=folders, tabs * feat: Stop using pinned manager and use zen session sidebar, b=no-bug, c=common, folders, tabs, workspaces * feat: Dont restore windows that are already initialized, b=no-bug, c=no-component * chore: Update patches to ff 145, b=no-bug, c=no-component * Discard changes to src/browser/components/sessionstore/SessionStore-sys-mjs.patch * Discard changes to src/browser/components/tabbrowser/content/tab-js.patch * Discard changes to src/browser/components/tabbrowser/content/tabbrowser-js.patch * Discard changes to src/zen/tabs/ZenPinnedTabsStorage.mjs * feat: Run session saver before opening a new winodw, b=no-bug, c=tabs * feat: Clone the previous state, b=no-bug, c=no-component * feat: Move window sync to its own JS module, b=no-bug, c=workspaces * feat: Run session saver before opening a new window, b=no-bug, c=no-component * feat: Full cross-window workspace syncing, b=no-bug, c=workspaces * feat: Also change icons and labels if the tab is pending, b=no-bug, c=tabs, workspaces * feat: Dont session duplicate the tabs, b=no-bug, c=workspaces * feat: Start on new session restore, b=no-bug, c=no-component * feat: Properly handle tab moves, b=no-bug, c=workspaces * Discard changes to prefs/browser.yaml * feat: Start doing out own session restore, b=no-bug, c=folders, tabs * feat: Stop using pinned manager and use zen session sidebar, b=no-bug, c=common, folders, tabs, workspaces * feat: Dont restore windows that are already initialized, b=no-bug, c=no-component * chore: Update patches to ff 145, b=no-bug, c=no-component * Discard changes to src/browser/components/sessionstore/SessionStore-sys-mjs.patch * Discard changes to src/browser/components/tabbrowser/content/tab-js.patch * Discard changes to src/browser/components/tabbrowser/content/tabbrowser-js.patch * Discard changes to src/zen/tabs/ZenPinnedTabsStorage.mjs * feat: Run session saver before opening a new winodw, b=no-bug, c=tabs * feat: Clone the previous state, b=no-bug, c=no-component * feat: Move window sync to its own JS module, b=no-bug, c=workspaces * feat: Run session saver before opening a new window, b=no-bug, c=no-component * feat: Start making use of IDs instead of sync identifiers, b=no-bug, c=folders * feat: Listen to new tab opens for new sync system, b=no-bug, c=common, folders, tabs * feat: Listen for more tab events and properly sync them, b=no-bug, c=common, folders, tabs * feat: Start moving browser views to the selected windows, b=no-bug, c=no-component * chore: Remove extra patch, b=no-bug, c=no-component * feat: Leave a screenshot of the page behind when switching windows or tabs, b=no-bug, c=common * feat: Run session saves right before writing and quiting, b=no-bug, c=common * fix: Fixed going back to a different window not allowing to type on inputs, b=no-bug, c=no-component * feat: Start syncing folders as well, b=no-bug, c=folders * Discard changes to src/browser/components/tabbrowser/content/tab-js.patch * chore: Update patches to ff 146, b=no-bug, c=no-component * feat: Early support for unsynced windoiws, b=no-bug, c=workspaces * fix: Move back active views when closing a window, b=no-bug, c=no-component * feat: Stop rendering sub-layers when swaping browsers, b=no-bug, c=common * feat: Improved support for unsynced windows support, b=no-bug, c=workspaces, folders * feat: Implemented 'Move To...' Button for unsynced windows, b=no-bug, c=workspaces, common * feat: Make sure to properly flush all windows when making a new one and fix removing progress listeners, b=no-bug, c=workspaces * feat: Make sure to not lose any tabs when opening from a private window, b=no-bug, c=workspaces * feat: Allow unload to run instantly and fix closing windows on mac, b=no-bug, c=no-component * feat: Make sure to always initialize an empty state with the sidebar object, b=no-bug, c=workspaces * chore: Small fixes and QA checks, b=no-bug, c=tabs, workspaces * fix: Fixed tab labels not changing on unfocused windows, b=no-bug, c=no-component * feat: Fixed closing windows on macos not returning to the original views, b=no-bug, c=no-component * chore: Turn off debug flags by default, b=no-bug, c=no-component * feat: Start implementing old pinned tab behaviour we used to have, b=no-bug, c=common, tabs * feat: Unsynced windows should always be allowed to change labels, b=no-bug, c=welcome * feat: Make sure we wait long enough before we initialize workspaces, b=no-bug, c=workspaces * feat: Dont mix remoteness when changing browser views and restore window spaces, b=no-bug, c=common, folders, workspaces * test: Fixed tests for the pinned tabs manager, b=no-bug, c=tabs, folders, tests, welcome * feat: Added partial support for split views, b=no-bug, c=split-view * chore: Finished basic support for split views, b=no-bug, c=folders, split-view * feat: Always make sure to save the last closed window to the sidebar object, b=no-bug, c=no-component * feat: Implement workspace sync store into the session file, b=closes #10857, c=common, tabs, tests, workspaces * feat: New drag and drop system, b=no-bug, c=tabs, common, folders * feat: Add support for drag-and-dropping tabs into groups, b=no-bug, c=common, folders, tabs, workspaces * feat: Add a default value for the workspace cache, b=no-bug, c=workspaces * fix: Default assign an array instead of an object to the workspaces cache, b=no-bug, c=workspaces * feat: Take into consideration win data may not have allocated spaces, b=no-bug, c=workspaces * feat: Always make sure we are assigning the correct space ID, b=no-bug, c=workspaces * feat: Make sure to initialize windows even if there are no tabs, b=no-bug, c=no-component * feat: Improved drag and drop simulation, b=no-bug, c=common, tabs * feat: Implement opacity changes to the drag image, b=no-bug, c=tabs, common, split-view * feat: Support for drag and dropping outside the window, b=no-bug, c=split-view * feat: Added transitions when reordering, b=no-bug, c=split-view, tabs * feat: Started working on drag and dropping to essentials, b=no-bug, c=no-component * Discard changes to locales/en-US/browser/browser/zen-workspaces.ftl * Discard changes to prefs/zen/view.yaml * Discard changes to prefs/zen/zen.yaml * Discard changes to src/browser/base/content/zen-assets.inc.xhtml * Discard changes to src/browser/base/content/zen-assets.jar.inc.mn * Discard changes to src/browser/base/content/zen-panels/popups.inc * Discard changes to src/browser/base/content/zen-preloaded.inc.xhtml * Discard changes to src/browser/components/places/content/editBookmark-js.patch * Discard changes to src/browser/components/sessionstore/SessionStore-sys-mjs.patch * Discard changes to src/browser/components/sessionstore/TabState-sys-mjs.patch * Discard changes to src/browser/components/tabbrowser/content/tab-js.patch * Discard changes to src/browser/components/urlbar/UrlbarProviderPlaces-sys-mjs.patch * Discard changes to src/zen/ZenComponents.manifest * Discard changes to src/browser/components/tabbrowser/content/tabbrowser-js.patch * feat: Finish migration, b=no-bug, c=no-component * feat: Add support for multi tabs dragging, b=no-bug, c=tabs * feat: Added support for essential tabs, b=no-bug, c=split-view, tabs, workspaces * feat: Added support to switch space when holding on the side of the sidebar, b=no-bug, c=common, split-view, workspaces * Discard changes to src/browser/components/tabbrowser/content/tabbrowser-js.patch * chore: Fixed merge conflicts, b=no-bug, c=no-component * feat: Added support for split views, b=no-bug, c=split-view --------- Signed-off-by: mr. m <91018726+mr-cheffy@users.noreply.github.com>
This commit is contained in:
@@ -40,12 +40,6 @@
|
||||
- name: zen.view.window.scheme
|
||||
value: 2
|
||||
|
||||
- name: zen.view.drag-and-drop.move-over-threshold
|
||||
value: 70
|
||||
|
||||
- name: zen.view.drag-and-drop.edge-zone-threshold
|
||||
value: 25
|
||||
|
||||
- name: zen.view.context-menu.refresh
|
||||
value: '@IS_TWILIGHT@'
|
||||
|
||||
|
||||
@@ -20,6 +20,15 @@
|
||||
- name: zen.tabs.close-window-with-empty
|
||||
value: true
|
||||
|
||||
- name: zen.tabs.use-legacy-drag-and-drop
|
||||
value: false
|
||||
|
||||
- name: zen.tabs.folder-dragover-threshold-percent
|
||||
value: 20 # Percentage of folder height to trigger dragover
|
||||
|
||||
- name: zen.tabs.dnd-switch-space-delay
|
||||
value: 1000 # milliseconds
|
||||
|
||||
- name: zen.ctrlTab.show-pending-tabs
|
||||
value: false
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include ../../../zen/common/jar.inc.mn
|
||||
#include ../../../zen/compact-mode/jar.inc.mn
|
||||
#include ../../../zen/drag-and-drop/jar.inc.mn
|
||||
#include ../../../zen/split-view/jar.inc.mn
|
||||
#include ../../../zen/mods/jar.inc.mn
|
||||
#include ../../../zen/workspaces/jar.inc.mn
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/drag-and-drop.js b/browser/components/tabbrowser/content/drag-and-drop.js
|
||||
index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9548dce83 100644
|
||||
index 97b931c3c7385a52d20204369fcf6d6999053687..6a136cf14d0bc081507a05f298f12ac7a7914601 100644
|
||||
--- a/browser/components/tabbrowser/content/drag-and-drop.js
|
||||
+++ b/browser/components/tabbrowser/content/drag-and-drop.js
|
||||
@@ -32,6 +32,9 @@
|
||||
@@ -12,26 +12,33 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
if (isTab(element)) {
|
||||
return element;
|
||||
}
|
||||
@@ -112,6 +115,10 @@
|
||||
@@ -112,6 +115,9 @@
|
||||
}
|
||||
|
||||
let draggedTab = event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||
+ if (draggedTab && dropEffect === "move") {
|
||||
+ gZenPinnedTabManager.applyDragoverClass(event, draggedTab);
|
||||
+ gZenViewSplitter.onBrowserDragEndToSplit(event);
|
||||
+ }
|
||||
if (
|
||||
(dropEffect == "move" || dropEffect == "copy") &&
|
||||
document == draggedTab.ownerDocument &&
|
||||
@@ -266,6 +273,18 @@
|
||||
@@ -130,10 +136,6 @@
|
||||
|
||||
// Pinned tabs in expanded vertical mode are on a grid format and require
|
||||
// different logic to drag and drop.
|
||||
- if (this._isContainerVerticalPinnedGrid(draggedTab)) {
|
||||
- this._animateExpandedPinnedTabMove(event);
|
||||
- return;
|
||||
- }
|
||||
this._animateTabMove(event);
|
||||
return;
|
||||
}
|
||||
@@ -266,6 +268,15 @@
|
||||
|
||||
this._tabDropIndicator.hidden = true;
|
||||
event.stopPropagation();
|
||||
+ if (draggedTab?.hasAttribute("zen-has-splitted")) {
|
||||
+ draggedTab.removeAttribute("zen-has-splitted");
|
||||
+ draggedTab._visuallySelected = false;
|
||||
+ }
|
||||
+ if (draggedTab && dropEffect == "move") {
|
||||
+ this.handle_drop_transition?.(draggedTab._dragData.dropElement, draggedTab, movingTabs, draggedTab._dragData.dropBefore);
|
||||
+ let moved = gZenPinnedTabManager.moveToAnotherTabContainerIfNecessary(event, movingTabs);
|
||||
+
|
||||
+ if (moved) {
|
||||
@@ -42,7 +49,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
if (draggedTab && dropEffect == "copy") {
|
||||
let duplicatedDraggedTab;
|
||||
let duplicatedTabs = [];
|
||||
@@ -291,8 +310,9 @@
|
||||
@@ -291,8 +302,9 @@
|
||||
let translateOffsetY = oldTranslateY % tabHeight;
|
||||
let newTranslateX = oldTranslateX - translateOffsetX;
|
||||
let newTranslateY = oldTranslateY - translateOffsetY;
|
||||
@@ -54,7 +61,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
|
||||
if (this._isContainerVerticalPinnedGrid(draggedTab)) {
|
||||
// Update both translate axis for pinned vertical expanded tabs
|
||||
@@ -308,8 +328,8 @@
|
||||
@@ -308,8 +320,8 @@
|
||||
}
|
||||
} else {
|
||||
let tabs = this._tabbrowserTabs.ariaFocusableItems.slice(
|
||||
@@ -65,7 +72,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
);
|
||||
let size = this._tabbrowserTabs.verticalMode ? "height" : "width";
|
||||
let screenAxis = this._tabbrowserTabs.verticalMode
|
||||
@@ -362,11 +382,13 @@
|
||||
@@ -362,11 +374,13 @@
|
||||
this._dragToPinPromoCard,
|
||||
];
|
||||
let shouldPin =
|
||||
@@ -79,7 +86,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
isTab(draggedTab) &&
|
||||
draggedTab.pinned &&
|
||||
this._tabbrowserTabs.arrowScrollbox.contains(event.target);
|
||||
@@ -384,6 +406,7 @@
|
||||
@@ -384,6 +398,7 @@
|
||||
(oldTranslateY && oldTranslateY != newTranslateY);
|
||||
} else if (this._tabbrowserTabs.verticalMode) {
|
||||
shouldTranslate &&= oldTranslateY && oldTranslateY != newTranslateY;
|
||||
@@ -87,7 +94,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
} else {
|
||||
shouldTranslate &&= oldTranslateX && oldTranslateX != newTranslateX;
|
||||
}
|
||||
@@ -440,7 +463,7 @@
|
||||
@@ -440,7 +455,7 @@
|
||||
item.removeAttribute("tabdrop-samewindow");
|
||||
resolve();
|
||||
};
|
||||
@@ -96,7 +103,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
postTransitionCleanup();
|
||||
} else {
|
||||
let onTransitionEnd = transitionendEvent => {
|
||||
@@ -581,6 +604,7 @@
|
||||
@@ -581,6 +596,7 @@
|
||||
|
||||
let nextItem = this._tabbrowserTabs.ariaFocusableItems[newIndex];
|
||||
let tabGroup = isTab(nextItem) && nextItem.group;
|
||||
@@ -104,7 +111,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
gBrowser.loadTabs(urls, {
|
||||
inBackground,
|
||||
replace,
|
||||
@@ -618,7 +642,16 @@
|
||||
@@ -618,7 +634,16 @@
|
||||
this._expandGroupOnDrop(draggedTab);
|
||||
}
|
||||
this._resetTabsAfterDrop(draggedTab.ownerDocument);
|
||||
@@ -122,7 +129,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
if (
|
||||
dt.mozUserCancelled ||
|
||||
dt.dropEffect != "none" ||
|
||||
@@ -822,7 +855,10 @@
|
||||
@@ -822,7 +847,10 @@
|
||||
_getDragTarget(event, { ignoreSides = false } = {}) {
|
||||
let { target } = event;
|
||||
while (target) {
|
||||
@@ -134,7 +141,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
break;
|
||||
}
|
||||
target = target.parentNode;
|
||||
@@ -839,14 +875,17 @@
|
||||
@@ -839,14 +867,17 @@
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -154,7 +161,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
!this._tabbrowserTabs.expandOnHover
|
||||
);
|
||||
}
|
||||
@@ -877,7 +916,8 @@
|
||||
@@ -877,7 +908,8 @@
|
||||
isTabGroupLabel(draggedTab) &&
|
||||
draggedTab._dragData?.expandGroupOnDrop
|
||||
) {
|
||||
@@ -164,19 +171,23 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
}
|
||||
}
|
||||
|
||||
@@ -942,10 +982,7 @@
|
||||
if (this._isContainerVerticalPinnedGrid(tab)) {
|
||||
// In expanded vertical mode, the max number of pinned tabs per row is dynamic
|
||||
// Set this before adjusting dragged tab's position
|
||||
- let pinnedTabs = this._tabbrowserTabs.visibleTabs.slice(
|
||||
- 0,
|
||||
- gBrowser.pinnedTabCount
|
||||
- );
|
||||
+ let pinnedTabs = this._tabbrowserTabs.ariaFocusableItems.slice(0, gBrowser._numZenEssentials);
|
||||
let tabsPerRow = 0;
|
||||
let position = RTL_UI
|
||||
? window.windowUtils.getBoundsWithoutFlushing(
|
||||
@@ -1112,7 +1149,7 @@
|
||||
@@ -1055,7 +1087,6 @@
|
||||
// using updateDragImage. On Linux, we can use a panel.
|
||||
if (platform == "win" || platform == "macosx") {
|
||||
captureListener = function () {
|
||||
- dt.updateDragImage(canvas, dragImageOffset, dragImageOffset);
|
||||
};
|
||||
} else {
|
||||
// Create a panel to use it in setDragImage
|
||||
@@ -1093,7 +1124,6 @@
|
||||
);
|
||||
dragImageOffset = dragImageOffset * scale;
|
||||
}
|
||||
- dt.setDragImage(toDrag, dragImageOffset, dragImageOffset);
|
||||
|
||||
// _dragData.offsetX/Y give the coordinates that the mouse should be
|
||||
// positioned relative to the corner of the new window created upon
|
||||
@@ -1112,7 +1142,7 @@
|
||||
let dropEffect = this.getDropEffectForTabDrag(event);
|
||||
let isMovingInTabStrip = !fromTabList && dropEffect == "move";
|
||||
let collapseTabGroupDuringDrag =
|
||||
@@ -185,7 +196,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
|
||||
tab._dragData = {
|
||||
offsetX: this._tabbrowserTabs.verticalMode
|
||||
@@ -1122,7 +1159,7 @@
|
||||
@@ -1122,7 +1152,7 @@
|
||||
? event.screenY - window.screenY - tabOffset
|
||||
: event.screenY - window.screenY,
|
||||
scrollPos:
|
||||
@@ -194,7 +205,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
? this._tabbrowserTabs.pinnedTabsContainer.scrollPosition
|
||||
: this._tabbrowserTabs.arrowScrollbox.scrollPosition,
|
||||
screenX: event.screenX,
|
||||
@@ -1149,6 +1186,7 @@
|
||||
@@ -1149,6 +1179,7 @@
|
||||
|
||||
if (collapseTabGroupDuringDrag) {
|
||||
tab.group.collapsed = true;
|
||||
@@ -202,224 +213,15 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1173,6 +1211,16 @@
|
||||
@@ -1173,6 +1204,7 @@
|
||||
if (tabStripItemElement.hasAttribute("dragtarget")) {
|
||||
return;
|
||||
}
|
||||
+ let { movingTabs: zenMovingTabs } = tab._dragData;
|
||||
+ for (let movingTab of zenMovingTabs.slice(zenMovingTabs.findIndex(t => t._tPos == tab._tPos))) {
|
||||
+ if (isTabGroupLabel(tab)) {
|
||||
+ movingTab = movingTab.parentElement;
|
||||
+ }
|
||||
+ // "dragtarget" contains the following rules which must only be set AFTER the above
|
||||
+ // elements have been adjusted. {z-index: 3 !important, position: absolute !important}
|
||||
+ movingTab.setAttribute("zen-dragtarget", "");
|
||||
+ }
|
||||
+ return;
|
||||
let isPinned = tab.pinned;
|
||||
let numPinned = gBrowser.pinnedTabCount;
|
||||
let allTabs = this._tabbrowserTabs.ariaFocusableItems;
|
||||
@@ -1624,10 +1672,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
- let tabs = this._tabbrowserTabs.visibleTabs.slice(
|
||||
- 0,
|
||||
- gBrowser.pinnedTabCount
|
||||
- );
|
||||
+ let tabs = this._tabbrowserTabs.ariaFocusableItems.slice(0, gBrowser._numZenEssentials);
|
||||
|
||||
let directionX = screenX > dragData.animLastScreenX;
|
||||
let directionY = screenY > dragData.animLastScreenY;
|
||||
@@ -1636,6 +1681,8 @@
|
||||
|
||||
let { width: tabWidth, height: tabHeight } =
|
||||
draggedTab.getBoundingClientRect();
|
||||
+ tabWidth += 4; // Add 4px to account for the gap
|
||||
+ tabHeight += 4;
|
||||
let shiftSizeX = tabWidth * movingTabs.length;
|
||||
let shiftSizeY = tabHeight;
|
||||
dragData.tabWidth = tabWidth;
|
||||
@@ -1672,8 +1719,8 @@
|
||||
let lastBoundX =
|
||||
lastTabInRow.screenX +
|
||||
lastTabInRow.getBoundingClientRect().width -
|
||||
- (lastMovingTabScreenX + tabWidth);
|
||||
- let lastBoundY = periphery.screenY - (lastMovingTabScreenY + tabHeight);
|
||||
+ (lastMovingTabScreenX + tabWidth) + 4;
|
||||
+ let lastBoundY = lastTab.screenY - lastMovingTabScreenY;
|
||||
translateX = Math.min(Math.max(translateX, firstBoundX), lastBoundX);
|
||||
translateY = Math.min(Math.max(translateY, firstBoundY), lastBoundY);
|
||||
|
||||
@@ -1833,13 +1880,18 @@
|
||||
this._clearDragOverGroupingTimer();
|
||||
this.#clearPinnedDropIndicatorTimer();
|
||||
|
||||
- let isPinned = draggedTab.pinned;
|
||||
- let numPinned = gBrowser.pinnedTabCount;
|
||||
+ let isPinned = draggedTab?.group ? draggedTab.group.pinned : draggedTab.pinned;
|
||||
+ let numPinned = gBrowser._numVisiblePinTabsWithoutCollapsed;
|
||||
+ let essential = draggedTab.hasAttribute("zen-essential");
|
||||
+ const isDraggingFolder = isTabGroupLabel(draggedTab) && draggedTab.group?.isZenFolder;
|
||||
let allTabs = this._tabbrowserTabs.ariaFocusableItems;
|
||||
let tabs = allTabs.slice(
|
||||
- isPinned ? 0 : numPinned,
|
||||
- isPinned ? numPinned : undefined
|
||||
+ (isPinned && essential) ? 0 : gBrowser._numZenEssentials,
|
||||
+ isPinned ? (essential ? gBrowser._numZenEssentials : (isDraggingFolder ? numPinned : undefined)) : undefined
|
||||
);
|
||||
+ if (draggedTab.group?.hasAttribute("split-view-group")) {
|
||||
+ draggedTab = draggedTab.group.labelElement;
|
||||
+ }
|
||||
|
||||
if (this._rtlMode) {
|
||||
tabs.reverse();
|
||||
@@ -1854,7 +1906,7 @@
|
||||
let translateAxis = this._tabbrowserTabs.verticalMode
|
||||
? "translateY"
|
||||
: "translateX";
|
||||
- let { width: tabWidth, height: tabHeight } = bounds(draggedTab);
|
||||
+ let { width: tabWidth, height: tabHeight } = bounds(draggedTab.group?.hasAttribute("split-view-group") ? draggedTab.group : draggedTab);
|
||||
let tabSize = this._tabbrowserTabs.verticalMode ? tabHeight : tabWidth;
|
||||
let translateX = event.screenX - dragData.screenX;
|
||||
let translateY = event.screenY - dragData.screenY;
|
||||
@@ -1870,6 +1922,12 @@
|
||||
);
|
||||
let lastMovingTab = movingTabs.at(-1);
|
||||
let firstMovingTab = movingTabs[0];
|
||||
+ if (lastMovingTab.group?.hasAttribute("split-view-group")) {
|
||||
+ lastMovingTab = lastMovingTab.group;
|
||||
+ }
|
||||
+ if (firstMovingTab.group?.hasAttribute("split-view-group")) {
|
||||
+ firstMovingTab = firstMovingTab.group;
|
||||
+ }
|
||||
let endEdge = ele => ele[screenAxis] + bounds(ele)[size];
|
||||
let lastMovingTabScreen = endEdge(lastMovingTab);
|
||||
let firstMovingTabScreen = firstMovingTab[screenAxis];
|
||||
@@ -1884,6 +1942,13 @@
|
||||
let endBound = this._rtlMode
|
||||
? endEdge(this._tabbrowserTabs) - lastMovingTabScreen
|
||||
: periphery[screenAxis] - 1 - lastMovingTabScreen;
|
||||
+ {
|
||||
+ let firstTab = tabs.at(this._rtlMode ? -1 : 0);
|
||||
+ let lastTab = tabs.at(this._rtlMode ? 0 : -1);
|
||||
+ startBound = firstTab[screenAxis] - firstMovingTabScreen;
|
||||
+ endBound = endEdge(lastTab) - lastMovingTabScreen;
|
||||
+ endBound = gZenPinnedTabManager.getLastTabBound(endBound, lastTab, isDraggingFolder);
|
||||
+ }
|
||||
translate = Math.min(Math.max(translate, startBound), endBound);
|
||||
|
||||
// Center the tab under the cursor if the tab is not under the cursor while dragging
|
||||
@@ -2075,6 +2140,8 @@
|
||||
};
|
||||
|
||||
let dropElement = getOverlappedElement();
|
||||
+ if (dropElement?.hasAttribute("split-view-group")) dropElement = dropElement.labelElement;
|
||||
+ gZenPinnedTabManager.animateSeparatorMove(movingTabs, dropElement, isPinned, event);
|
||||
|
||||
let newDropElementIndex;
|
||||
if (dropElement) {
|
||||
@@ -2157,7 +2224,7 @@
|
||||
? Services.prefs.getIntPref(
|
||||
"browser.tabs.dragDrop.moveOverThresholdPercent"
|
||||
) / 100
|
||||
- : 0.5;
|
||||
+ : Services.prefs.getIntPref('zen.view.drag-and-drop.move-over-threshold') / 100;
|
||||
moveOverThreshold = Math.min(1, Math.max(0, moveOverThreshold));
|
||||
let shouldMoveOver = overlapPercent > moveOverThreshold;
|
||||
if (logicalForward && shouldMoveOver) {
|
||||
@@ -2190,6 +2257,7 @@
|
||||
// If dragging a group over another group, don't make it look like it is
|
||||
// possible to drop the dragged group inside the other group.
|
||||
if (
|
||||
+ false &&
|
||||
isTabGroupLabel(draggedTab) &&
|
||||
dropElement?.group &&
|
||||
(!dropElement.group.collapsed ||
|
||||
@@ -2216,20 +2284,13 @@
|
||||
let isOutOfBounds = isPinned
|
||||
? dropElement.elementIndex >= numPinned
|
||||
: dropElement.elementIndex < numPinned;
|
||||
- if (isOutOfBounds) {
|
||||
- // Drop after last pinned tab
|
||||
- dropElement = this._tabbrowserTabs.ariaFocusableItems[numPinned - 1];
|
||||
- dropBefore = false;
|
||||
- }
|
||||
}
|
||||
|
||||
- if (
|
||||
- gBrowser._tabGroupsEnabled &&
|
||||
- isTab(draggedTab) &&
|
||||
- !isPinned &&
|
||||
- (!numPinned || newDropElementIndex >= numPinned)
|
||||
- ) {
|
||||
+ if (isTab(draggedTab) || isTabGroupLabel(draggedTab)) {
|
||||
let dragOverGroupingThreshold = 1 - moveOverThreshold;
|
||||
+ if (draggedTab && !dropElement?.group) {
|
||||
+ gZenFolders.highlightGroupOnDragOver(null);
|
||||
+ }
|
||||
let groupingDelay = Services.prefs.getIntPref(
|
||||
"browser.tabs.dragDrop.createGroup.delayMS"
|
||||
);
|
||||
@@ -2237,6 +2298,7 @@
|
||||
// When dragging tab(s) over an ungrouped tab, signal to the user
|
||||
// that dropping the tab(s) will create a new tab group.
|
||||
let shouldCreateGroupOnDrop =
|
||||
+ false &&
|
||||
!movingTabsSet.has(dropElement) &&
|
||||
isTab(dropElement) &&
|
||||
!dropElement?.group &&
|
||||
@@ -2245,6 +2307,7 @@
|
||||
// When dragging tab(s) over a collapsed tab group label, signal to the
|
||||
// user that dropping the tab(s) will add them to the group.
|
||||
let shouldDropIntoCollapsedTabGroup =
|
||||
+ false &&
|
||||
isTabGroupLabel(dropElement) &&
|
||||
dropElement.group.collapsed &&
|
||||
overlapPercent > dragOverGroupingThreshold;
|
||||
@@ -2302,6 +2365,14 @@
|
||||
dropElement = dropElementGroup.tabs[0];
|
||||
dropBefore = true;
|
||||
}
|
||||
+ ({ dropElement, colorCode, dropBefore } = gZenFolders.handleDragOverTabGroupLabel(
|
||||
+ dropElement,
|
||||
+ draggedTab,
|
||||
+ overlapPercent,
|
||||
+ movingTabs,
|
||||
+ dropBefore,
|
||||
+ colorCode
|
||||
+ ));
|
||||
}
|
||||
this._setDragOverGroupColor(colorCode);
|
||||
this._tabbrowserTabs.toggleAttribute(
|
||||
@@ -2324,10 +2395,11 @@
|
||||
dragData.dropBefore = dropBefore;
|
||||
dragData.animDropElementIndex = newDropElementIndex;
|
||||
|
||||
+ gZenFolders.setFolderIndentation(movingTabs, dropElement);
|
||||
// Shift background tabs to leave a gap where the dragged tab
|
||||
// would currently be dropped.
|
||||
for (let item of tabs) {
|
||||
- if (item == draggedTab) {
|
||||
+ if (item == draggedTab || (item.group?.hasAttribute("split-view-group") && item.group == draggedTab.group)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2417,11 +2489,13 @@
|
||||
}
|
||||
|
||||
finishAnimateTabMove() {
|
||||
+ gZenPinnedTabManager.onDragFinish();
|
||||
if (!this.#isMovingTab()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#setMovingTabMode(false);
|
||||
+ gZenFolders.highlightGroupOnDragOver(null);
|
||||
|
||||
for (let item of this._tabbrowserTabs.ariaFocusableItems) {
|
||||
this._resetGroupTarget(item);
|
||||
@@ -2457,7 +2531,7 @@
|
||||
@@ -2457,7 +2489,7 @@
|
||||
tab.style.left = "";
|
||||
tab.style.top = "";
|
||||
tab.style.maxWidth = "";
|
||||
@@ -428,7 +230,7 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..bc49f4f5a90638d725eca016d00f30d9
|
||||
}
|
||||
for (let label of draggedTabDocument.getElementsByClassName(
|
||||
"tab-group-label-container"
|
||||
@@ -2467,7 +2541,7 @@
|
||||
@@ -2467,7 +2499,7 @@
|
||||
label.style.left = "";
|
||||
label.style.top = "";
|
||||
label.style.maxWidth = "";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d797de7be 100644
|
||||
index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..00a9810cc894b6a21adb78b70a15049cc1db3edf 100644
|
||||
--- a/browser/components/tabbrowser/content/tabbrowser.js
|
||||
+++ b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
@@ -386,6 +386,7 @@
|
||||
@@ -87,7 +87,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
tab.linkedPanel = uniqueId;
|
||||
this._selectedTab = tab;
|
||||
this._selectedBrowser = browser;
|
||||
@@ -898,13 +951,17 @@
|
||||
@@ -898,13 +951,18 @@
|
||||
}
|
||||
|
||||
this.showTab(aTab);
|
||||
@@ -100,17 +100,21 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
);
|
||||
// If periphery is null, append to end
|
||||
- this.pinnedTabsContainer.insertBefore(aTab, periphery);
|
||||
+ this.tabContainer.tabDragAndDrop.handle_drop_transition(this.tabs[this.pinnedTabCount - 1], aTab, [aTab], false);
|
||||
+ aTab.hasAttribute("zen-essential") ? gZenWorkspaces.getEssentialsSection(aTab).appendChild(aTab) : this.pinnedTabsContainer.insertBefore(aTab, this.pinnedTabsContainer.lastChild)
|
||||
});
|
||||
+ }
|
||||
|
||||
aTab.setAttribute("pinned", "true");
|
||||
this._updateTabBarForPinnedTabs();
|
||||
@@ -917,11 +974,15 @@
|
||||
@@ -917,11 +975,18 @@
|
||||
}
|
||||
|
||||
this.#handleTabMove(aTab, () => {
|
||||
+ const handled = gZenFolders.handleTabUnpin(aTab);
|
||||
+ if (!handled) {
|
||||
+ this.tabContainer.tabDragAndDrop.handle_drop_transition(this.tabs[this.pinnedTabCount + 1 /* empty + extra */], aTab, [aTab], true);
|
||||
+ }
|
||||
+
|
||||
// we remove this attribute first, so that allTabs represents
|
||||
// the moving of a tab from the pinned tabs container
|
||||
@@ -123,7 +127,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
});
|
||||
|
||||
aTab.style.marginInlineStart = "";
|
||||
@@ -1098,6 +1159,9 @@
|
||||
@@ -1098,6 +1163,9 @@
|
||||
|
||||
let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"];
|
||||
|
||||
@@ -133,7 +137,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (
|
||||
aIconURL &&
|
||||
!LOCAL_PROTOCOLS.some(protocol => aIconURL.startsWith(protocol))
|
||||
@@ -1107,6 +1171,9 @@
|
||||
@@ -1107,6 +1175,9 @@
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -143,7 +147,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
|
||||
let browser = this.getBrowserForTab(aTab);
|
||||
browser.mIconURL = aIconURL;
|
||||
@@ -1379,7 +1446,6 @@
|
||||
@@ -1379,7 +1450,6 @@
|
||||
|
||||
// Preview mode should not reset the owner
|
||||
if (!this._previewMode && !oldTab.selected) {
|
||||
@@ -151,7 +155,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
}
|
||||
|
||||
let lastRelatedTab = this._lastRelatedTabMap.get(oldTab);
|
||||
@@ -1470,6 +1536,7 @@
|
||||
@@ -1470,6 +1540,7 @@
|
||||
if (!this._previewMode) {
|
||||
newTab.recordTimeFromUnloadToReload();
|
||||
newTab.updateLastAccessed();
|
||||
@@ -159,7 +163,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
oldTab.updateLastAccessed();
|
||||
// if this is the foreground window, update the last-seen timestamps.
|
||||
if (this.ownerGlobal == BrowserWindowTracker.getTopWindow()) {
|
||||
@@ -1622,6 +1689,9 @@
|
||||
@@ -1622,6 +1693,9 @@
|
||||
}
|
||||
|
||||
let activeEl = document.activeElement;
|
||||
@@ -169,7 +173,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
// If focus is on the old tab, move it to the new tab.
|
||||
if (activeEl == oldTab) {
|
||||
newTab.focus();
|
||||
@@ -1945,6 +2015,11 @@
|
||||
@@ -1945,6 +2019,11 @@
|
||||
}
|
||||
|
||||
_setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) {
|
||||
@@ -181,7 +185,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (!aLabel || aLabel.includes("about:reader?")) {
|
||||
return false;
|
||||
}
|
||||
@@ -2053,7 +2128,7 @@
|
||||
@@ -2053,7 +2132,7 @@
|
||||
newIndex = this.selectedTab._tPos + 1;
|
||||
}
|
||||
|
||||
@@ -190,7 +194,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (this.isTabGroupLabel(targetTab)) {
|
||||
throw new Error(
|
||||
"Replacing a tab group label with a tab is not supported"
|
||||
@@ -2328,6 +2403,7 @@
|
||||
@@ -2328,6 +2407,7 @@
|
||||
uriIsAboutBlank,
|
||||
userContextId,
|
||||
skipLoad,
|
||||
@@ -198,7 +202,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
} = {}) {
|
||||
let b = document.createXULElement("browser");
|
||||
// Use the JSM global to create the permanentKey, so that if the
|
||||
@@ -2401,8 +2477,7 @@
|
||||
@@ -2401,8 +2481,7 @@
|
||||
// we use a different attribute name for this?
|
||||
b.setAttribute("name", name);
|
||||
}
|
||||
@@ -208,7 +212,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
b.setAttribute("transparent", "true");
|
||||
}
|
||||
|
||||
@@ -2567,7 +2642,7 @@
|
||||
@@ -2567,7 +2646,7 @@
|
||||
|
||||
let panel = this.getPanel(browser);
|
||||
let uniqueId = this._generateUniquePanelID();
|
||||
@@ -217,7 +221,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
aTab.linkedPanel = uniqueId;
|
||||
|
||||
// Inject the <browser> into the DOM if necessary.
|
||||
@@ -2626,8 +2701,8 @@
|
||||
@@ -2626,8 +2705,8 @@
|
||||
// If we transitioned from one browser to two browsers, we need to set
|
||||
// hasSiblings=false on both the existing browser and the new browser.
|
||||
if (this.tabs.length == 2) {
|
||||
@@ -228,7 +232,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
} else {
|
||||
aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1;
|
||||
}
|
||||
@@ -2814,7 +2889,6 @@
|
||||
@@ -2814,7 +2893,6 @@
|
||||
this.selectedTab = this.addTrustedTab(BROWSER_NEW_TAB_URL, {
|
||||
tabIndex: tab._tPos + 1,
|
||||
userContextId: tab.userContextId,
|
||||
@@ -236,7 +240,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
focusUrlBar: true,
|
||||
});
|
||||
resolve(this.selectedBrowser);
|
||||
@@ -2923,6 +2997,9 @@
|
||||
@@ -2923,6 +3001,9 @@
|
||||
schemelessInput,
|
||||
hasValidUserGestureActivation = false,
|
||||
textDirectiveUserActivation = false,
|
||||
@@ -246,7 +250,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
} = {}
|
||||
) {
|
||||
// all callers of addTab that pass a params object need to pass
|
||||
@@ -2933,10 +3010,17 @@
|
||||
@@ -2933,10 +3014,17 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -264,7 +268,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
// If we're opening a foreground tab, set the owner by default.
|
||||
ownerTab ??= inBackground ? null : this.selectedTab;
|
||||
|
||||
@@ -2944,6 +3028,7 @@
|
||||
@@ -2944,6 +3032,7 @@
|
||||
if (this.selectedTab.owner) {
|
||||
this.selectedTab.owner = null;
|
||||
}
|
||||
@@ -272,7 +276,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
|
||||
// Find the tab that opened this one, if any. This is used for
|
||||
// determining positioning, and inherited attributes such as the
|
||||
@@ -2996,6 +3081,21 @@
|
||||
@@ -2996,6 +3085,21 @@
|
||||
noInitialLabel,
|
||||
skipBackgroundNotify,
|
||||
});
|
||||
@@ -294,7 +298,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (insertTab) {
|
||||
// Insert the tab into the tab container in the correct position.
|
||||
this.#insertTabAtIndex(t, {
|
||||
@@ -3004,6 +3104,7 @@
|
||||
@@ -3004,6 +3108,7 @@
|
||||
ownerTab,
|
||||
openerTab,
|
||||
pinned,
|
||||
@@ -302,7 +306,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
bulkOrderedOpen,
|
||||
tabGroup: tabGroup ?? openerTab?.group,
|
||||
});
|
||||
@@ -3022,6 +3123,7 @@
|
||||
@@ -3022,6 +3127,7 @@
|
||||
openWindowInfo,
|
||||
skipLoad,
|
||||
triggeringRemoteType,
|
||||
@@ -310,7 +314,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
}));
|
||||
|
||||
if (focusUrlBar) {
|
||||
@@ -3146,6 +3248,12 @@
|
||||
@@ -3146,6 +3252,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,7 +327,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
// Additionally send pinned tab events
|
||||
if (pinned) {
|
||||
this.#notifyPinnedStatus(t);
|
||||
@@ -3349,10 +3457,10 @@
|
||||
@@ -3349,10 +3461,10 @@
|
||||
isAdoptingGroup = false,
|
||||
isUserTriggered = false,
|
||||
telemetryUserCreateSource = "unknown",
|
||||
@@ -335,7 +339,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
}
|
||||
|
||||
if (!color) {
|
||||
@@ -3373,9 +3481,14 @@
|
||||
@@ -3373,9 +3485,14 @@
|
||||
label,
|
||||
isAdoptingGroup
|
||||
);
|
||||
@@ -352,7 +356,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
);
|
||||
group.addTabs(tabs);
|
||||
|
||||
@@ -3496,7 +3609,7 @@
|
||||
@@ -3496,7 +3613,7 @@
|
||||
}
|
||||
|
||||
this.#handleTabMove(tab, () =>
|
||||
@@ -361,7 +365,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3698,6 +3811,7 @@
|
||||
@@ -3698,6 +3815,7 @@
|
||||
openWindowInfo,
|
||||
skipLoad,
|
||||
triggeringRemoteType,
|
||||
@@ -369,7 +373,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
}
|
||||
) {
|
||||
// If we don't have a preferred remote type (or it is `NOT_REMOTE`), and
|
||||
@@ -3767,6 +3881,7 @@
|
||||
@@ -3767,6 +3885,7 @@
|
||||
openWindowInfo,
|
||||
name,
|
||||
skipLoad,
|
||||
@@ -377,7 +381,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3955,7 +4070,7 @@
|
||||
@@ -3955,7 +4074,7 @@
|
||||
// Add a new tab if needed.
|
||||
if (!tab) {
|
||||
let createLazyBrowser =
|
||||
@@ -386,7 +390,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
|
||||
let url = "about:blank";
|
||||
if (tabData.entries?.length) {
|
||||
@@ -3992,8 +4107,10 @@
|
||||
@@ -3992,8 +4111,10 @@
|
||||
insertTab: false,
|
||||
skipLoad: true,
|
||||
preferredRemoteType,
|
||||
@@ -398,7 +402,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (select) {
|
||||
tabToSelect = tab;
|
||||
}
|
||||
@@ -4005,7 +4122,8 @@
|
||||
@@ -4005,7 +4126,8 @@
|
||||
this.pinTab(tab);
|
||||
// Then ensure all the tab open/pinning information is sent.
|
||||
this._fireTabOpen(tab, {});
|
||||
@@ -408,7 +412,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
let { groupId } = tabData;
|
||||
const tabGroup = tabGroupWorkingData.get(groupId);
|
||||
// if a tab refers to a tab group we don't know, skip any group
|
||||
@@ -4019,7 +4137,10 @@
|
||||
@@ -4019,7 +4141,10 @@
|
||||
tabGroup.stateData.id,
|
||||
tabGroup.stateData.color,
|
||||
tabGroup.stateData.collapsed,
|
||||
@@ -420,7 +424,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
);
|
||||
tabsFragment.appendChild(tabGroup.node);
|
||||
}
|
||||
@@ -4064,9 +4185,23 @@
|
||||
@@ -4064,9 +4189,23 @@
|
||||
// to remove the old selected tab.
|
||||
if (tabToSelect) {
|
||||
let leftoverTab = this.selectedTab;
|
||||
@@ -436,15 +440,15 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
+ gZenWorkspaces._initialTab._shouldRemove = true;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ }
|
||||
+ else {
|
||||
+ gZenWorkspaces._tabToRemoveForEmpty = this.selectedTab;
|
||||
+ }
|
||||
}
|
||||
+ this._hasAlreadyInitializedZenSessionStore = true;
|
||||
|
||||
if (tabs.length > 1 || !tabs[0].selected) {
|
||||
this._updateTabsAfterInsert();
|
||||
@@ -4257,11 +4392,14 @@
|
||||
@@ -4257,11 +4396,14 @@
|
||||
if (ownerTab) {
|
||||
tab.owner = ownerTab;
|
||||
}
|
||||
@@ -460,7 +464,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (
|
||||
!bulkOrderedOpen &&
|
||||
((openerTab &&
|
||||
@@ -4273,7 +4411,7 @@
|
||||
@@ -4273,7 +4415,7 @@
|
||||
let lastRelatedTab =
|
||||
openerTab && this._lastRelatedTabMap.get(openerTab);
|
||||
let previousTab = lastRelatedTab || openerTab || this.selectedTab;
|
||||
@@ -469,7 +473,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
tabGroup = previousTab.group;
|
||||
}
|
||||
if (
|
||||
@@ -4284,7 +4422,7 @@
|
||||
@@ -4284,7 +4426,7 @@
|
||||
) {
|
||||
elementIndex = Infinity;
|
||||
} else if (previousTab.visible) {
|
||||
@@ -478,7 +482,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
} else if (previousTab == FirefoxViewHandler.tab) {
|
||||
elementIndex = 0;
|
||||
}
|
||||
@@ -4312,14 +4450,14 @@
|
||||
@@ -4312,14 +4454,14 @@
|
||||
}
|
||||
// Ensure index is within bounds.
|
||||
if (tab.pinned) {
|
||||
@@ -497,7 +501,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
|
||||
if (pinned && !itemAfter?.pinned) {
|
||||
itemAfter = null;
|
||||
@@ -4330,7 +4468,7 @@
|
||||
@@ -4330,7 +4472,7 @@
|
||||
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
|
||||
@@ -506,7 +510,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (this.isTab(itemAfter) && itemAfter.group == tabGroup) {
|
||||
// Place at the front of, or between tabs in, the same tab group
|
||||
this.tabContainer.insertBefore(tab, itemAfter);
|
||||
@@ -4358,7 +4496,11 @@
|
||||
@@ -4358,7 +4500,11 @@
|
||||
const tabContainer = pinned
|
||||
? this.tabContainer.pinnedTabsContainer
|
||||
: this.tabContainer;
|
||||
@@ -518,7 +522,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
}
|
||||
|
||||
this._updateTabsAfterInsert();
|
||||
@@ -4366,6 +4508,7 @@
|
||||
@@ -4366,6 +4512,7 @@
|
||||
if (pinned) {
|
||||
this._updateTabBarForPinnedTabs();
|
||||
}
|
||||
@@ -526,7 +530,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
|
||||
TabBarVisibility.update();
|
||||
}
|
||||
@@ -4916,6 +5059,7 @@
|
||||
@@ -4916,6 +5063,7 @@
|
||||
telemetrySource,
|
||||
} = {}
|
||||
) {
|
||||
@@ -534,7 +538,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
// When 'closeWindowWithLastTab' pref is enabled, closing all tabs
|
||||
// can be considered equivalent to closing the window.
|
||||
if (
|
||||
@@ -5005,6 +5149,7 @@
|
||||
@@ -5005,6 +5153,7 @@
|
||||
if (lastToClose) {
|
||||
this.removeTab(lastToClose, aParams);
|
||||
}
|
||||
@@ -542,7 +546,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@@ -5043,6 +5188,12 @@
|
||||
@@ -5043,6 +5192,12 @@
|
||||
aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start();
|
||||
}
|
||||
|
||||
@@ -555,7 +559,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
// Handle requests for synchronously removing an already
|
||||
// asynchronously closing tab.
|
||||
if (!animate && aTab.closing) {
|
||||
@@ -5057,6 +5208,9 @@
|
||||
@@ -5057,6 +5212,9 @@
|
||||
// state).
|
||||
let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width;
|
||||
let isLastTab = this.#isLastTabInWindow(aTab);
|
||||
@@ -565,7 +569,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (
|
||||
!this._beginRemoveTab(aTab, {
|
||||
closeWindowFastpath: true,
|
||||
@@ -5105,7 +5259,13 @@
|
||||
@@ -5105,7 +5263,13 @@
|
||||
// We're not animating, so we can cancel the animation stopwatch.
|
||||
Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId);
|
||||
aTab._closeTimeAnimTimerId = null;
|
||||
@@ -580,7 +584,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5239,7 +5399,7 @@
|
||||
@@ -5239,7 +5403,7 @@
|
||||
closeWindowWithLastTab != null
|
||||
? closeWindowWithLastTab
|
||||
: !window.toolbar.visible ||
|
||||
@@ -589,7 +593,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
|
||||
if (closeWindow) {
|
||||
// We've already called beforeunload on all the relevant tabs if we get here,
|
||||
@@ -5263,6 +5423,7 @@
|
||||
@@ -5263,6 +5427,7 @@
|
||||
|
||||
newTab = true;
|
||||
}
|
||||
@@ -597,7 +601,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
aTab._endRemoveArgs = [closeWindow, newTab];
|
||||
|
||||
// swapBrowsersAndCloseOther will take care of closing the window without animation.
|
||||
@@ -5303,13 +5464,7 @@
|
||||
@@ -5303,13 +5468,7 @@
|
||||
aTab._mouseleave();
|
||||
|
||||
if (newTab) {
|
||||
@@ -612,7 +616,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
} else {
|
||||
TabBarVisibility.update();
|
||||
}
|
||||
@@ -5442,6 +5597,7 @@
|
||||
@@ -5442,6 +5601,7 @@
|
||||
this.tabs[i]._tPos = i;
|
||||
}
|
||||
|
||||
@@ -620,7 +624,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (!this._windowIsClosing) {
|
||||
// update tab close buttons state
|
||||
this.tabContainer._updateCloseButtons();
|
||||
@@ -5663,6 +5819,7 @@
|
||||
@@ -5663,6 +5823,7 @@
|
||||
}
|
||||
|
||||
let excludeTabs = new Set(aExcludeTabs);
|
||||
@@ -628,7 +632,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
|
||||
// If this tab has a successor, it should be selectable, since
|
||||
// hiding or closing a tab removes that tab as a successor.
|
||||
@@ -5675,13 +5832,13 @@
|
||||
@@ -5675,13 +5836,13 @@
|
||||
!excludeTabs.has(aTab.owner) &&
|
||||
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")
|
||||
) {
|
||||
@@ -644,7 +648,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
);
|
||||
|
||||
let tab = this.tabContainer.findNextTab(aTab, {
|
||||
@@ -5697,7 +5854,7 @@
|
||||
@@ -5697,7 +5858,7 @@
|
||||
}
|
||||
|
||||
if (tab) {
|
||||
@@ -653,7 +657,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
}
|
||||
|
||||
// If no qualifying visible tab was found, see if there is a tab in
|
||||
@@ -5718,7 +5875,7 @@
|
||||
@@ -5718,7 +5879,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -662,7 +666,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
}
|
||||
|
||||
_blurTab(aTab) {
|
||||
@@ -5729,7 +5886,7 @@
|
||||
@@ -5729,7 +5890,7 @@
|
||||
* @returns {boolean}
|
||||
* False if swapping isn't permitted, true otherwise.
|
||||
*/
|
||||
@@ -671,7 +675,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
// Do not allow transfering a private tab to a non-private window
|
||||
// and vice versa.
|
||||
if (
|
||||
@@ -5783,6 +5940,7 @@
|
||||
@@ -5783,6 +5944,7 @@
|
||||
// fire the beforeunload event in the process. Close the other
|
||||
// window if this was its last tab.
|
||||
if (
|
||||
@@ -679,7 +683,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
!remoteBrowser._beginRemoveTab(aOtherTab, {
|
||||
adoptedByTab: aOurTab,
|
||||
closeWindowWithLastTab: true,
|
||||
@@ -5794,7 +5952,7 @@
|
||||
@@ -5794,7 +5956,7 @@
|
||||
// If this is the last tab of the window, hide the window
|
||||
// immediately without animation before the docshell swap, to avoid
|
||||
// about:blank being painted.
|
||||
@@ -688,7 +692,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (closeWindow) {
|
||||
let win = aOtherTab.ownerGlobal;
|
||||
win.windowUtils.suppressAnimation(true);
|
||||
@@ -5918,11 +6076,13 @@
|
||||
@@ -5918,11 +6080,13 @@
|
||||
}
|
||||
|
||||
// Finish tearing down the tab that's going away.
|
||||
@@ -702,7 +706,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
|
||||
this.setTabTitle(aOurTab);
|
||||
|
||||
@@ -6124,10 +6284,10 @@
|
||||
@@ -6124,10 +6288,10 @@
|
||||
SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
|
||||
}
|
||||
|
||||
@@ -715,7 +719,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
aTab.selected ||
|
||||
aTab.closing ||
|
||||
// Tabs that are sharing the screen, microphone or camera cannot be hidden.
|
||||
@@ -6185,7 +6345,8 @@
|
||||
@@ -6185,7 +6349,8 @@
|
||||
*
|
||||
* @param {MozTabbrowserTab|MozTabbrowserTabGroup|MozTabbrowserTabGroup.labelElement} aTab
|
||||
*/
|
||||
@@ -725,7 +729,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (this.tabs.length == 1) {
|
||||
return null;
|
||||
}
|
||||
@@ -6209,12 +6370,14 @@
|
||||
@@ -6209,12 +6374,14 @@
|
||||
}
|
||||
|
||||
// tell a new window to take the "dropped" tab
|
||||
@@ -741,7 +745,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6319,7 +6482,7 @@
|
||||
@@ -6319,7 +6486,7 @@
|
||||
* `true` if element is a `<tab-group>`
|
||||
*/
|
||||
isTabGroup(element) {
|
||||
@@ -750,7 +754,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6404,8 +6567,8 @@
|
||||
@@ -6404,8 +6571,8 @@
|
||||
}
|
||||
|
||||
// Don't allow mixing pinned and unpinned tabs.
|
||||
@@ -761,7 +765,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
} else {
|
||||
tabIndex = Math.max(tabIndex, this.pinnedTabCount);
|
||||
}
|
||||
@@ -6431,10 +6594,16 @@
|
||||
@@ -6431,10 +6598,16 @@
|
||||
this.#handleTabMove(
|
||||
element,
|
||||
() => {
|
||||
@@ -780,7 +784,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
if (neighbor && this.isTab(element) && tabIndex > element._tPos) {
|
||||
neighbor.after(element);
|
||||
} else {
|
||||
@@ -6492,23 +6661,28 @@
|
||||
@@ -6492,23 +6665,28 @@
|
||||
#moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) {
|
||||
if (this.isTabGroupLabel(targetElement)) {
|
||||
targetElement = targetElement.group;
|
||||
@@ -815,7 +819,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
} else if (!element.pinned && targetElement && targetElement.pinned) {
|
||||
// If the caller asks to move an unpinned element next to a pinned
|
||||
// tab, move the unpinned element to be the first unpinned element
|
||||
@@ -6521,14 +6695,34 @@
|
||||
@@ -6521,14 +6699,34 @@
|
||||
// move the tab group right before the first unpinned tab.
|
||||
// 4. Moving a tab group and the first unpinned tab is grouped:
|
||||
// move the tab group right before the first unpinned tab's tab group.
|
||||
@@ -851,7 +855,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
element.pinned
|
||||
? this.tabContainer.pinnedTabsContainer
|
||||
: this.tabContainer;
|
||||
@@ -6537,7 +6731,7 @@
|
||||
@@ -6537,7 +6735,7 @@
|
||||
element,
|
||||
() => {
|
||||
if (moveBefore) {
|
||||
@@ -860,7 +864,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
} else if (targetElement) {
|
||||
targetElement.after(element);
|
||||
} else {
|
||||
@@ -6607,10 +6801,10 @@
|
||||
@@ -6607,10 +6805,10 @@
|
||||
* @param {TabMetricsContext} [metricsContext]
|
||||
*/
|
||||
moveTabToGroup(aTab, aGroup, metricsContext) {
|
||||
@@ -873,7 +877,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
return;
|
||||
}
|
||||
if (aTab.group && aTab.group.id === aGroup.id) {
|
||||
@@ -6656,6 +6850,7 @@
|
||||
@@ -6656,6 +6854,7 @@
|
||||
|
||||
let state = {
|
||||
tabIndex: tab._tPos,
|
||||
@@ -881,7 +885,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
};
|
||||
if (tab.visible) {
|
||||
state.elementIndex = tab.elementIndex;
|
||||
@@ -6682,7 +6877,7 @@
|
||||
@@ -6682,7 +6881,7 @@
|
||||
let changedTabGroup =
|
||||
previousTabState.tabGroupId != currentTabState.tabGroupId;
|
||||
|
||||
@@ -890,7 +894,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
tab.dispatchEvent(
|
||||
new CustomEvent("TabMove", {
|
||||
bubbles: true,
|
||||
@@ -6723,6 +6918,10 @@
|
||||
@@ -6723,6 +6922,10 @@
|
||||
|
||||
moveActionCallback();
|
||||
|
||||
@@ -901,17 +905,16 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
// Clear tabs cache after moving nodes because the order of tabs may have
|
||||
// changed.
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
@@ -6815,6 +7014,9 @@
|
||||
@@ -6815,6 +7018,8 @@
|
||||
params.userContextId = aTab.getAttribute("usercontextid");
|
||||
}
|
||||
let newTab = this.addWebTab("about:blank", params);
|
||||
+ newTab._zenContentsVisible = true;
|
||||
+ newTab.zenStaticLabel = aTab.zenStaticLabel;
|
||||
+ newTab.zenStaticIcon = aTab.zenStaticIcon;
|
||||
let newBrowser = this.getBrowserForTab(newTab);
|
||||
|
||||
aTab.container.tabDragAndDrop.finishAnimateTabMove();
|
||||
@@ -7623,7 +7825,7 @@
|
||||
@@ -7623,7 +7828,7 @@
|
||||
// preventDefault(). It will still raise the window if appropriate.
|
||||
break;
|
||||
}
|
||||
@@ -920,7 +923,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
window.focus();
|
||||
aEvent.preventDefault();
|
||||
break;
|
||||
@@ -7640,7 +7842,6 @@
|
||||
@@ -7640,7 +7845,6 @@
|
||||
}
|
||||
case "TabGroupCollapse":
|
||||
aEvent.target.tabs.forEach(tab => {
|
||||
@@ -928,7 +931,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
});
|
||||
break;
|
||||
case "TabGroupCreateByUser":
|
||||
@@ -8589,6 +8790,7 @@
|
||||
@@ -8589,6 +8793,7 @@
|
||||
aWebProgress.isTopLevel
|
||||
) {
|
||||
this.mTab.setAttribute("busy", "true");
|
||||
@@ -936,7 +939,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
gBrowser._tabAttrModified(this.mTab, ["busy"]);
|
||||
this.mTab._notselectedsinceload = !this.mTab.selected;
|
||||
}
|
||||
@@ -8670,6 +8872,7 @@
|
||||
@@ -8670,6 +8875,7 @@
|
||||
// known defaults. Note we use the original URL since about:newtab
|
||||
// redirects to a prerendered page.
|
||||
const shouldRemoveFavicon =
|
||||
@@ -944,7 +947,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d
|
||||
!this.mBrowser.mIconURL &&
|
||||
!ignoreBlank &&
|
||||
!(originalLocation.spec in FAVICON_DEFAULTS);
|
||||
@@ -9623,7 +9826,7 @@ var TabContextMenu = {
|
||||
@@ -9623,7 +9829,7 @@ var TabContextMenu = {
|
||||
);
|
||||
contextUnpinSelectedTabs.hidden =
|
||||
!this.contextTab.pinned || !this.multiselected;
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js
|
||||
index 6b6c04599fe80983d13d2069ca62b99d8ad70271..04144081560f1678dc9673736ef2bd9d9ca3f478 100644
|
||||
index 6b6c04599fe80983d13d2069ca62b99d8ad70271..6d5ae983446bc778f3075d79f8ff14748dd7756f 100644
|
||||
--- a/browser/components/tabbrowser/content/tabs.js
|
||||
+++ b/browser/components/tabbrowser/content/tabs.js
|
||||
@@ -235,7 +235,7 @@
|
||||
true
|
||||
)
|
||||
? new window.TabStacking(this)
|
||||
- : new window.TabDragAndDrop(this);
|
||||
+ : Services.prefs.getBoolPref("zen.tabs.use-legacy-drag-and-drop") ? new window.TabDragAndDrop(this) : new window.ZenDragAndDrop(this);
|
||||
this.tabDragAndDrop.init();
|
||||
}
|
||||
|
||||
@@ -436,7 +436,7 @@
|
||||
// and we're not hitting the scroll buttons.
|
||||
if (
|
||||
|
||||
47
src/widget/cocoa/nsDragService-mm.patch
Normal file
47
src/widget/cocoa/nsDragService-mm.patch
Normal file
@@ -0,0 +1,47 @@
|
||||
diff --git a/widget/cocoa/nsDragService.mm b/widget/cocoa/nsDragService.mm
|
||||
index f1614b823a859ff8fbc74982f205bb1f2ef29beb..897c24846a97c132babe3ad79da12ebfcec90484 100644
|
||||
--- a/widget/cocoa/nsDragService.mm
|
||||
+++ b/widget/cocoa/nsDragService.mm
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/DocumentInlines.h"
|
||||
+#include "mozilla/nsZenDragAndDrop.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsCocoaUtils.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
@@ -148,6 +149,10 @@
|
||||
bitsPerPixel:32];
|
||||
|
||||
uint8_t* dest = [imageRep bitmapData];
|
||||
+ auto drag_translucency = DRAG_TRANSLUCENCY;
|
||||
+ if (auto zenDragAndDrop = zen::nsZenDragAndDrop::GetZenDragAndDropInstance()) {
|
||||
+ drag_translucency = zenDragAndDrop->GetDragImageOpacity();
|
||||
+ }
|
||||
for (uint32_t i = 0; i < height; ++i) {
|
||||
uint8_t* src = map.mData + i * map.mStride;
|
||||
for (uint32_t j = 0; j < width; ++j) {
|
||||
@@ -155,15 +160,15 @@
|
||||
// is premultipled here. Also, Quartz likes RGBA, so do that translation
|
||||
// as well.
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
- dest[0] = uint8_t(src[1] * DRAG_TRANSLUCENCY);
|
||||
- dest[1] = uint8_t(src[2] * DRAG_TRANSLUCENCY);
|
||||
- dest[2] = uint8_t(src[3] * DRAG_TRANSLUCENCY);
|
||||
- dest[3] = uint8_t(src[0] * DRAG_TRANSLUCENCY);
|
||||
+ dest[0] = uint8_t(src[1] * drag_translucency);
|
||||
+ dest[1] = uint8_t(src[2] * drag_translucency);
|
||||
+ dest[2] = uint8_t(src[3] * drag_translucency);
|
||||
+ dest[3] = uint8_t(src[0] * drag_translucency);
|
||||
#else
|
||||
- dest[0] = uint8_t(src[2] * DRAG_TRANSLUCENCY);
|
||||
- dest[1] = uint8_t(src[1] * DRAG_TRANSLUCENCY);
|
||||
- dest[2] = uint8_t(src[0] * DRAG_TRANSLUCENCY);
|
||||
- dest[3] = uint8_t(src[3] * DRAG_TRANSLUCENCY);
|
||||
+ dest[0] = uint8_t(src[2] * drag_translucency);
|
||||
+ dest[1] = uint8_t(src[1] * drag_translucency);
|
||||
+ dest[2] = uint8_t(src[0] * drag_translucency);
|
||||
+ dest[3] = uint8_t(src[3] * drag_translucency);
|
||||
#endif
|
||||
src += 4;
|
||||
dest += 4;
|
||||
@@ -11,4 +11,6 @@
|
||||
ChromeUtils.importESModule("chrome://browser/content/zen-components/ZenMods.mjs", { global: "current" });
|
||||
ChromeUtils.importESModule("chrome://browser/content/zen-components/ZenKeyboardShortcuts.mjs", { global: "current" });
|
||||
ChromeUtils.importESModule("chrome://browser/content/zen-components/ZenSessionStore.mjs", { global: "current" });
|
||||
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenDragAndDrop.js", this);
|
||||
}
|
||||
|
||||
@@ -1223,6 +1223,7 @@ window.gZenVerticalTabsManager = {
|
||||
|
||||
// Always move the splitter next to the sidebar
|
||||
const splitter = document.getElementById('zen-sidebar-splitter');
|
||||
splitter.addEventListener('dragover', gBrowser.tabContainer);
|
||||
this.navigatorToolbox.after(splitter);
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
if (!isCompactMode) {
|
||||
|
||||
1223
src/zen/drag-and-drop/ZenDragAndDrop.js
Normal file
1223
src/zen/drag-and-drop/ZenDragAndDrop.js
Normal file
File diff suppressed because it is too large
Load Diff
14
src/zen/drag-and-drop/components.conf
Normal file
14
src/zen/drag-and-drop/components.conf
Normal file
@@ -0,0 +1,14 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
Classes = [
|
||||
{
|
||||
'cid': '{f8714110-1fb1-4129-abad-887a64e4085e}',
|
||||
'interfaces': ['nsIZenDragAndDrop'],
|
||||
'contract_ids': ['@mozilla.org/zen/drag-and-drop;1'],
|
||||
'type': 'zen::nsZenDragAndDrop',
|
||||
'headers': ['mozilla/nsZenDragAndDrop.h'],
|
||||
'processes': ProcessSelector.MAIN_PROCESS_ONLY,
|
||||
},
|
||||
]
|
||||
5
src/zen/drag-and-drop/jar.inc.mn
Normal file
5
src/zen/drag-and-drop/jar.inc.mn
Normal file
@@ -0,0 +1,5 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
content/browser/zen-components/ZenDragAndDrop.js (../../zen/drag-and-drop/ZenDragAndDrop.js)
|
||||
31
src/zen/drag-and-drop/moz.build
Normal file
31
src/zen/drag-and-drop/moz.build
Normal file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
"nsIZenDragAndDrop.idl",
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
"nsZenDragAndDrop.h",
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
"nsZenDragAndDrop.cpp",
|
||||
]
|
||||
|
||||
XPCOM_MANIFESTS += [
|
||||
"components.conf",
|
||||
]
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
"/dom/base",
|
||||
"/layout/base",
|
||||
"/widget",
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
XPIDL_MODULE = "zen_dnd"
|
||||
25
src/zen/drag-and-drop/nsIZenDragAndDrop.idl
Normal file
25
src/zen/drag-and-drop/nsIZenDragAndDrop.idl
Normal file
@@ -0,0 +1,25 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* @brief Interface for Zen's drag and drop functionality.
|
||||
*/
|
||||
[scriptable, uuid(f8714110-1fb1-4129-abad-887a64e4085e)]
|
||||
interface nsIZenDragAndDrop : nsISupports {
|
||||
/**
|
||||
* @brief Indicate that a drag operation has started. Note
|
||||
* that this should only be called for zen's drag and drop
|
||||
* operations for the tabs.
|
||||
* @param opacity The opacity of the drag image.
|
||||
*/
|
||||
void onDragStart(in float opacity);
|
||||
|
||||
/**
|
||||
* @brief Indicate that a drag operation has ended.
|
||||
*/
|
||||
void onDragEnd();
|
||||
};
|
||||
|
||||
48
src/zen/drag-and-drop/nsZenDragAndDrop.cpp
Normal file
48
src/zen/drag-and-drop/nsZenDragAndDrop.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsZenDragAndDrop.h"
|
||||
#include "nsBaseDragService.h"
|
||||
|
||||
namespace zen {
|
||||
namespace {
|
||||
|
||||
static constexpr auto kZenDefaultDragImageOpacity =
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
// For GTK, the default is 0.5 (DRAG_IMAGE_ALPHA_LEVEL) to match
|
||||
// the native behavior. Make sure its synced with the following variable:
|
||||
// https://searchfox.org/firefox-main/rev/14c08f0368ead8bfdddec62f43e0bb5c8fd61289/widget/gtk/nsDragService.cpp#75
|
||||
0.5f;
|
||||
#else
|
||||
// For other platforms, the default is whatever the value of DRAG_TRANSLUCENCY
|
||||
// is, defined in nsBaseDragService.h
|
||||
DRAG_TRANSLUCENCY;
|
||||
#endif
|
||||
|
||||
} // namespace: <empty>
|
||||
|
||||
// Use the macro to inject all of the definitions for nsISupports.
|
||||
NS_IMPL_ISUPPORTS(nsZenDragAndDrop, nsIZenDragAndDrop)
|
||||
|
||||
nsZenDragAndDrop::nsZenDragAndDrop() {
|
||||
(void)this->OnDragEnd();
|
||||
}
|
||||
|
||||
auto nsZenDragAndDrop::GetZenDragAndDropInstance() -> nsCOMPtr<nsZenDragAndDrop> {
|
||||
return do_GetService(ZEN_BOOSTS_BACKEND_CONTRACTID);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsZenDragAndDrop::OnDragStart(float opacity) {
|
||||
mDragImageOpacity = opacity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsZenDragAndDrop::OnDragEnd() {
|
||||
mDragImageOpacity = kZenDefaultDragImageOpacity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace: zen
|
||||
45
src/zen/drag-and-drop/nsZenDragAndDrop.h
Normal file
45
src/zen/drag-and-drop/nsZenDragAndDrop.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_ZenDragAndDrop_h__
|
||||
#define mozilla_ZenDragAndDrop_h__
|
||||
|
||||
#include "nsIZenDragAndDrop.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#define ZEN_BOOSTS_BACKEND_CONTRACTID "@mozilla.org/zen/drag-and-drop;1"
|
||||
|
||||
namespace zen {
|
||||
|
||||
/**
|
||||
* @brief Implementation of the nsIZenDragAndDrop interface.
|
||||
* When we want to do a drag and drop operation, web standards
|
||||
* don't really allow much customization of the drag image.
|
||||
* This class allows Zen to have more control over the drag
|
||||
* and drop operations for the tabs.
|
||||
*/
|
||||
class nsZenDragAndDrop final : public nsIZenDragAndDrop {
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIZENDRAGANDDROP
|
||||
|
||||
public:
|
||||
explicit nsZenDragAndDrop();
|
||||
auto GetDragImageOpacity() const { return mDragImageOpacity; }
|
||||
|
||||
/**
|
||||
* @brief Get the singleton instance of nsZenDragAndDrop. There may be occasions
|
||||
* where it won't be available (e.g. on the content process), so this may return
|
||||
* nullptr.
|
||||
* @return nsZenDragAndDrop* The singleton instance, or nullptr if not available
|
||||
*/
|
||||
static auto GetZenDragAndDropInstance() -> nsCOMPtr<nsZenDragAndDrop>;
|
||||
|
||||
private:
|
||||
~nsZenDragAndDrop() = default;
|
||||
float mDragImageOpacity{};
|
||||
};
|
||||
|
||||
} // namespace zen
|
||||
|
||||
#endif
|
||||
@@ -6,7 +6,7 @@ export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
#initialized = false;
|
||||
|
||||
static markup = `
|
||||
<hbox class="tab-group-label-container" pack="center">
|
||||
<hbox class="tab-group-label-container zen-drop-target" pack="center">
|
||||
<html:div class="tab-group-folder-icon"/>
|
||||
<label class="tab-group-label" role="button"/>
|
||||
<image class="tab-reset-button reset-icon" role="button" keyNav="false" data-l10n-id="zen-folders-unload-all-tooltip"/>
|
||||
|
||||
@@ -33,8 +33,6 @@ function formatRelativeTime(timestamp) {
|
||||
|
||||
class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
#ZEN_MAX_SUBFOLDERS = Services.prefs.getIntPref('zen.folders.max-subfolders', 5);
|
||||
#ZEN_EDGE_ZONE_THRESHOLD =
|
||||
Services.prefs.getIntPref('zen.view.drag-and-drop.edge-zone-threshold', 25) / 100;
|
||||
|
||||
#popup = null;
|
||||
#popupTimer = null;
|
||||
@@ -1065,18 +1063,16 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
* @param {Array<MozTabbrowserTab>|null} movingTabs The tabs being moved.
|
||||
*/
|
||||
highlightGroupOnDragOver(folder, movingTabs) {
|
||||
if (folder === this.#lastHighlightedGroup) return;
|
||||
if (folder === this.#lastHighlightedGroup) return true;
|
||||
const tab = movingTabs ? movingTabs[0] : null;
|
||||
if (this.#lastHighlightedGroup && this.#lastHighlightedGroup !== folder) {
|
||||
this.#lastHighlightedGroup.removeAttribute('selected');
|
||||
if (this.#lastHighlightedGroup.collapsed) {
|
||||
this.updateFolderIcon(this.#lastHighlightedGroup, 'close');
|
||||
}
|
||||
this.#lastHighlightedGroup = null;
|
||||
}
|
||||
|
||||
if (
|
||||
folder &&
|
||||
folder?.isZenFolder &&
|
||||
(!folder.hasAttribute('split-view-group') || !folder.hasAttribute('selected')) &&
|
||||
folder !== tab?.group &&
|
||||
!(
|
||||
@@ -1084,13 +1080,13 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
movingTabs?.some((t) => gBrowser.isTabGroupLabel(t))
|
||||
)
|
||||
) {
|
||||
folder.setAttribute('selected', 'true');
|
||||
folder.style.transform = '';
|
||||
if (folder.collapsed) {
|
||||
this.updateFolderIcon(folder, 'open');
|
||||
}
|
||||
this.#lastHighlightedGroup = folder;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1103,54 +1099,6 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the dragover logic when dragging a tab or tab group label over another tab group label.
|
||||
* This function determines where the dragged item should be visually dropped (before/after the group, or inside it)
|
||||
* and updates related styling and highlighting.
|
||||
*
|
||||
* @param {MozTabbrowserTabGroupLabel} currentDropElement The tab group label currently being dragged over.
|
||||
* @param {MozTabbrowserTab|MozTabbrowserTabGroupLabel} draggedTab The tab or tab group label being dragged.
|
||||
* @param {number} overlapPercent The percentage of overlap between the dragged item and the drop target.
|
||||
* @param {Array<MozTabbrowserTab>} movingTabs An array of tabs that are currently being dragged together.
|
||||
* @param {boolean} currentDropBefore Indicates if the current drop position is before the middle of the drop element.
|
||||
* @param {string|undefined} currentColorCode The current color code for dragover highlighting.
|
||||
* @returns {{dropElement: MozTabbrowserTabGroup|MozTabbrowserTab|MozTabbrowserTabGroupLabel, colorCode: string|undefined, dropBefore: boolean}}
|
||||
* An object containing the updated drop element, color code for highlighting, and drop position.
|
||||
*/
|
||||
handleDragOverTabGroupLabel(
|
||||
currentDropElement,
|
||||
draggedTab,
|
||||
overlapPercent,
|
||||
movingTabs,
|
||||
currentDropBefore,
|
||||
currentColorCode
|
||||
) {
|
||||
let dropElement = currentDropElement;
|
||||
let dropBefore = currentDropBefore;
|
||||
let colorCode = currentColorCode;
|
||||
|
||||
const dropElementGroup = dropElement?.isZenFolder ? dropElement : dropElement?.group;
|
||||
const isSplitGroup = dropElement?.group?.hasAttribute('split-view-group');
|
||||
let firstGroupElem = dropElementGroup?.groupStartElement.nextElementSibling;
|
||||
if (gBrowser.isTabGroup(firstGroupElem)) firstGroupElem = firstGroupElem.labelElement;
|
||||
|
||||
const isInMiddleZone =
|
||||
overlapPercent >= this.#ZEN_EDGE_ZONE_THRESHOLD &&
|
||||
overlapPercent <= 1 - this.#ZEN_EDGE_ZONE_THRESHOLD;
|
||||
const shouldDropInside = isInMiddleZone && !isSplitGroup;
|
||||
|
||||
if (shouldDropInside) {
|
||||
dropElement = firstGroupElem;
|
||||
dropBefore = true;
|
||||
this.highlightGroupOnDragOver(dropElementGroup, movingTabs);
|
||||
} else {
|
||||
colorCode = undefined;
|
||||
this.highlightGroupOnDragOver(null);
|
||||
}
|
||||
|
||||
return { dropElement, colorCode, dropBefore };
|
||||
}
|
||||
|
||||
#normalizeGroupItems(items) {
|
||||
return items
|
||||
.filter((item) => !item.hasAttribute('zen-empty-tab'))
|
||||
|
||||
@@ -8,6 +8,7 @@ EXTRA_PP_COMPONENTS += [
|
||||
|
||||
DIRS += [
|
||||
"common",
|
||||
"drag-and-drop",
|
||||
"glance",
|
||||
"mods",
|
||||
"tests",
|
||||
|
||||
@@ -464,6 +464,12 @@ class nsZenWindowSync {
|
||||
}
|
||||
const relativeTab = this.#getItemFromWindow(aWindow, originalSibling.id);
|
||||
if (relativeTab) {
|
||||
gBrowser.tabContainer.tabDragAndDrop.handle_drop_transition(
|
||||
relativeTab,
|
||||
aTargetItem,
|
||||
[aTargetItem],
|
||||
false
|
||||
);
|
||||
relativeTab.after(aTargetItem);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -228,9 +228,26 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
|
||||
#getDragImageForSplit(tab) {
|
||||
const element = window.MozXULElement.parseXULToFragment(
|
||||
`
|
||||
<vbox id="zen-split-view-drag-image">
|
||||
<image />
|
||||
<label />
|
||||
</vbox>
|
||||
`
|
||||
).querySelector('#zen-split-view-drag-image');
|
||||
const image = element.querySelector('image');
|
||||
const label = element.querySelector('label');
|
||||
image.src = tab.getAttribute('image');
|
||||
label.textContent = tab.label;
|
||||
document.documentElement.appendChild(element);
|
||||
this._dndElement = element;
|
||||
return element;
|
||||
}
|
||||
|
||||
onBrowserDragOverToSplit(event) {
|
||||
if (this.fakeBrowser) {
|
||||
this.onBrowserDragEndToSplit(event);
|
||||
return;
|
||||
}
|
||||
var dt = event.dataTransfer;
|
||||
@@ -239,23 +256,20 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
// tab copy or move
|
||||
draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||
// not our drop then
|
||||
if (!draggedTab || gBrowser.selectedTab.hasAttribute('zen-empty-tab')) {
|
||||
if (!gBrowser.isTab(draggedTab) || gBrowser.selectedTab.hasAttribute('zen-empty-tab')) {
|
||||
return;
|
||||
}
|
||||
gBrowser.tabContainer.tabDragAndDrop.finishMoveTogetherSelectedTabs(draggedTab);
|
||||
}
|
||||
if (
|
||||
!draggedTab ||
|
||||
this._canDrop ||
|
||||
this._hasAnimated ||
|
||||
this.fakeBrowser ||
|
||||
!this._lastOpenedTab ||
|
||||
(this._lastOpenedTab &&
|
||||
this._lastOpenedTab.getAttribute('zen-workspace-id') !==
|
||||
draggedTab.getAttribute('zen-workspace-id') &&
|
||||
!this._lastOpenedTab.hasAttribute('zen-essential')) ||
|
||||
draggedTab === this._lastOpenedTab
|
||||
(this._lastOpenedTab.getAttribute('zen-workspace-id') !==
|
||||
draggedTab.getAttribute('zen-workspace-id') &&
|
||||
!this._lastOpenedTab.hasAttribute('zen-essential'))
|
||||
) {
|
||||
this._lastOpenedTab = gBrowser.selectedTab;
|
||||
}
|
||||
if (!draggedTab || this._canDrop || this._hasAnimated || this.fakeBrowser) {
|
||||
return;
|
||||
}
|
||||
if (draggedTab.splitView) {
|
||||
@@ -285,19 +299,25 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
return;
|
||||
}
|
||||
dt.mozCursor = 'default';
|
||||
if (!this._dndElement) {
|
||||
const originalDNDArgs = gBrowser.tabContainer.tabDragAndDrop.originalDragImageArgs;
|
||||
requestAnimationFrame(() => {
|
||||
dt.updateDragImage(
|
||||
this.#getDragImageForSplit(draggedTab),
|
||||
originalDNDArgs[1],
|
||||
originalDNDArgs[2]
|
||||
);
|
||||
});
|
||||
gBrowser.tabContainer.tabDragAndDrop.clearDragOverVisuals();
|
||||
}
|
||||
const oldTab = this._lastOpenedTab;
|
||||
this._canDrop = true;
|
||||
Services.zen.playHapticFeedback();
|
||||
{
|
||||
this._draggingTab = draggedTab;
|
||||
gBrowser.selectedTab = oldTab;
|
||||
this._hasAnimated = true;
|
||||
this.tabBrowserPanel.setAttribute('dragging-split', 'true');
|
||||
for (const tab of gBrowser.tabs) {
|
||||
tab.style.removeProperty('transform');
|
||||
if (tab.group) {
|
||||
tab.group.style.removeProperty('transform');
|
||||
}
|
||||
}
|
||||
// Add a min width to all the browser elements to prevent them from resizing
|
||||
const panelsWidth = gBrowser.tabbox.getBoundingClientRect().width;
|
||||
let numOfTabsToDivide = 2;
|
||||
@@ -330,11 +350,6 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
this.fakeBrowser.setAttribute('has-split-view', 'true');
|
||||
}
|
||||
gBrowser.tabbox.appendChild(this.fakeBrowser);
|
||||
this.fakeBrowser.style.setProperty(
|
||||
'--zen-split-view-fake-icon',
|
||||
`url(${draggedTab.getAttribute('image')})`
|
||||
);
|
||||
draggedTab._visuallySelected = true;
|
||||
this.fakeBrowser.setAttribute('side', side);
|
||||
this._finishAllAnimatingPromise = Promise.all([
|
||||
gZenUIManager.motion.animate(
|
||||
@@ -371,13 +386,14 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
]);
|
||||
if (this._finishAllAnimatingPromise) {
|
||||
this._finishAllAnimatingPromise.then(() => {
|
||||
draggedTab.linkedBrowser.docShellIsActive = false;
|
||||
draggedTab.linkedBrowser
|
||||
.closest('.browserSidebarContainer')
|
||||
.classList.remove('deck-selected');
|
||||
if (draggedTab !== oldTab) {
|
||||
draggedTab.linkedBrowser.docShellIsActive = false;
|
||||
draggedTab.linkedBrowser
|
||||
.closest('.browserSidebarContainer')
|
||||
.classList.remove('deck-selected');
|
||||
}
|
||||
this.fakeBrowser.addEventListener('dragleave', this.onBrowserDragEndToSplit);
|
||||
this._canDrop = true;
|
||||
draggedTab._visuallySelected = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -390,12 +406,11 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
const panelsRect = gBrowser.tabbox.getBoundingClientRect();
|
||||
const fakeBrowserRect = this.fakeBrowser && this.fakeBrowser.getBoundingClientRect();
|
||||
if (
|
||||
((event.target.closest('#tabbrowser-tabbox') && event.target != this.fakeBrowser) ||
|
||||
(fakeBrowserRect &&
|
||||
event.clientX > fakeBrowserRect.left &&
|
||||
event.clientX < fakeBrowserRect.left + fakeBrowserRect.width &&
|
||||
event.clientY > fakeBrowserRect.top &&
|
||||
event.clientY < fakeBrowserRect.top + fakeBrowserRect.height) ||
|
||||
((fakeBrowserRect &&
|
||||
event.clientX > fakeBrowserRect.left &&
|
||||
event.clientX < fakeBrowserRect.left + fakeBrowserRect.width &&
|
||||
event.clientY > fakeBrowserRect.top &&
|
||||
event.clientY < fakeBrowserRect.top + fakeBrowserRect.height) ||
|
||||
(event.screenX === 0 && event.screenY === 0)) && // It's equivalent to 0 if the event has been dropped
|
||||
!cancelled
|
||||
) {
|
||||
@@ -415,50 +430,47 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
if (!this.fakeBrowser) {
|
||||
return;
|
||||
}
|
||||
this.fakeBrowser.classList.add('fade-out');
|
||||
const side = this.fakeBrowser.getAttribute('side');
|
||||
if (this._draggingTab) this._draggingTab.setAttribute('zen-has-splitted', 'true');
|
||||
this._lastOpenedTab = gBrowser.selectedTab;
|
||||
this._draggingTab = null;
|
||||
try {
|
||||
this._canDrop = false;
|
||||
Promise.all([
|
||||
gZenUIManager.motion.animate(
|
||||
gBrowser.tabbox,
|
||||
side === 'left'
|
||||
gBrowser.tabContainer.tabDragAndDrop.clearSpaceSwitchTimer();
|
||||
event.dataTransfer.updateDragImage(
|
||||
...gBrowser.tabContainer.tabDragAndDrop.originalDragImageArgs
|
||||
);
|
||||
this._canDrop = false;
|
||||
Promise.all([
|
||||
gZenUIManager.motion.animate(
|
||||
gBrowser.tabbox,
|
||||
side === 'left'
|
||||
? {
|
||||
paddingLeft: [`${halfWidth}px`, 0],
|
||||
}
|
||||
: {
|
||||
paddingRight: [`${halfWidth}px`, 0],
|
||||
},
|
||||
{
|
||||
duration: 0.1,
|
||||
easing: 'ease-out',
|
||||
}
|
||||
),
|
||||
gZenUIManager.motion.animate(
|
||||
this.fakeBrowser,
|
||||
{
|
||||
width: [`${halfWidth - padding * 2}px`, 0],
|
||||
...(side === 'left'
|
||||
? {
|
||||
paddingLeft: [`${halfWidth}px`, 0],
|
||||
marginLeft: [`${-halfWidth}px`, 0],
|
||||
}
|
||||
: {
|
||||
paddingRight: [`${halfWidth}px`, 0],
|
||||
},
|
||||
{
|
||||
duration: 0.1,
|
||||
easing: 'ease-out',
|
||||
}
|
||||
),
|
||||
gZenUIManager.motion.animate(
|
||||
this.fakeBrowser,
|
||||
{
|
||||
width: [`${halfWidth - padding * 2}px`, 0],
|
||||
...(side === 'left'
|
||||
? {
|
||||
marginLeft: [`${-halfWidth}px`, 0],
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
{
|
||||
duration: 0.1,
|
||||
easing: 'ease-out',
|
||||
}
|
||||
),
|
||||
]).then(() => {
|
||||
this._maybeRemoveFakeBrowser();
|
||||
});
|
||||
} catch {
|
||||
this._canDrop = false;
|
||||
: {}),
|
||||
},
|
||||
{
|
||||
duration: 0.1,
|
||||
easing: 'ease-out',
|
||||
}
|
||||
),
|
||||
]).finally(() => {
|
||||
this._maybeRemoveFakeBrowser();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1667,11 +1679,14 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
_maybeRemoveFakeBrowser(select = true) {
|
||||
gBrowser.tabbox.removeAttribute('style');
|
||||
this.tabBrowserPanel.removeAttribute('dragging-split');
|
||||
if (this._dndElement) {
|
||||
this._dndElement.remove();
|
||||
delete this._dndElement;
|
||||
}
|
||||
if (this.fakeBrowser) {
|
||||
delete this._hasAnimated;
|
||||
this.fakeBrowser.remove();
|
||||
this.fakeBrowser = null;
|
||||
if (this._draggingTab) this._draggingTab._visuallySelected = false;
|
||||
if (select) {
|
||||
gBrowser.selectedTab = this._draggingTab;
|
||||
this._draggingTab = null;
|
||||
@@ -1728,6 +1743,12 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
return false;
|
||||
}
|
||||
|
||||
const droppedOnTab = gZenGlanceManager.getTabOrGlanceParent(gBrowser.getTabForBrowser(browser));
|
||||
if (droppedOnTab === this._draggingTab) {
|
||||
this.createEmptySplit(dropSide == 'right');
|
||||
return true;
|
||||
}
|
||||
|
||||
gBrowser.selectedTab = this._draggingTab;
|
||||
this._draggingTab = null;
|
||||
const browserContainer = draggedTab.linkedBrowser?.closest('.browserSidebarContainer');
|
||||
@@ -1735,7 +1756,6 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
browserContainer.style.opacity = '0';
|
||||
}
|
||||
|
||||
const droppedOnTab = gZenGlanceManager.getTabOrGlanceParent(gBrowser.getTabForBrowser(browser));
|
||||
if (droppedOnTab && droppedOnTab !== draggedTab) {
|
||||
// Calculate which side of the target browser the drop occurred
|
||||
// const browserRect = browser.getBoundingClientRect();
|
||||
@@ -1977,13 +1997,14 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
|
||||
createEmptySplit() {
|
||||
createEmptySplit(rightSide = true) {
|
||||
const selectedTab = gBrowser.selectedTab;
|
||||
const emptyTab = gZenWorkspaces._emptyTab;
|
||||
let tabs = rightSide ? [selectedTab, emptyTab] : [emptyTab, selectedTab];
|
||||
const data = {
|
||||
tabs: [selectedTab, emptyTab],
|
||||
tabs: tabs,
|
||||
gridType: 'grid',
|
||||
layoutTree: this.calculateLayoutTree([selectedTab, emptyTab], 'grid'),
|
||||
layoutTree: this.calculateLayoutTree(tabs, 'grid'),
|
||||
};
|
||||
this._data.push(data);
|
||||
this.activateSplitView(data);
|
||||
@@ -2016,7 +2037,11 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
this.removeTabFromGroup(emptyTab, groupIndex, { forUnsplit: true });
|
||||
gBrowser.selectedTab = selectedTab;
|
||||
this.resetTabState(emptyTab, false);
|
||||
this.splitTabs([selectedTab, newSelectedTab], 'grid', 1);
|
||||
this.splitTabs(
|
||||
rightSide ? [selectedTab, newSelectedTab] : [newSelectedTab, selectedTab],
|
||||
'grid',
|
||||
rightSide ? 1 : 0
|
||||
);
|
||||
} else {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@@ -210,31 +210,28 @@
|
||||
right: var(--zen-element-separation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 3.5rem;
|
||||
pointer-events: none;
|
||||
height: 3.5rem;
|
||||
background: var(--zen-split-view-fake-icon);
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
opacity: 0.8;
|
||||
transition: opacity 0.2s;
|
||||
transition-delay: 0.1s;
|
||||
#zen-split-view-drag-image {
|
||||
width: 200px;
|
||||
height: 250px;
|
||||
border-radius: 16px;
|
||||
background: black;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
gap: 20px;
|
||||
position: relative;
|
||||
|
||||
@starting-style {
|
||||
opacity: 0;
|
||||
}
|
||||
& image {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
&.fade-out::after {
|
||||
opacity: 0;
|
||||
transition-delay: 0s;
|
||||
& label {
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,12 +84,16 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
onTabIconChanged(tab, url = null) {
|
||||
tab.dispatchEvent(new CustomEvent('ZenTabIconChanged', { bubbles: true, detail: { tab } }));
|
||||
const iconUrl = url ?? tab.iconImage.src;
|
||||
if (tab.hasAttribute('zen-essential')) {
|
||||
tab.style.setProperty('--zen-essential-tab-icon', `url(${iconUrl})`);
|
||||
this.setEssentialTabIcon(tab, url);
|
||||
}
|
||||
}
|
||||
|
||||
setEssentialTabIcon(tab, url = null) {
|
||||
const iconUrl = url ?? tab.getAttribute('image') ?? '';
|
||||
tab.style.setProperty('--zen-essential-tab-icon', `url(${iconUrl})`);
|
||||
}
|
||||
|
||||
_onTabResetPinButton(event, tab) {
|
||||
event.stopPropagation();
|
||||
this._resetTabToStoredState(tab);
|
||||
@@ -534,15 +538,16 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
moveToAnotherTabContainerIfNecessary(event, movingTabs) {
|
||||
movingTabs = [...movingTabs];
|
||||
if (!this.enabled) {
|
||||
return false;
|
||||
}
|
||||
movingTabs = [...movingTabs];
|
||||
try {
|
||||
const pinnedTabsTarget =
|
||||
event.target.closest('.zen-current-workspace-indicator') || this._isGoingToPinnedTabs;
|
||||
const pinnedTabsTarget = event.target.closest(
|
||||
':is(.zen-current-workspace-indicator, .zen-workspace-pinned-tabs-section)'
|
||||
);
|
||||
const essentialTabsTarget = event.target.closest('.zen-essentials-container');
|
||||
const tabsTarget = !this._isGoingToPinnedTabs;
|
||||
const tabsTarget = !pinnedTabsTarget;
|
||||
|
||||
// TODO: Solve the issue of adding a tab between two groups
|
||||
// Remove group labels from the moving tabs and replace it
|
||||
@@ -685,9 +690,6 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
removeTabContainersDragoverClass(hideIndicator = true) {
|
||||
if (this._dragIndicator) {
|
||||
Services.zen.playHapticFeedback();
|
||||
}
|
||||
this.dragIndicator.remove();
|
||||
this._dragIndicator = null;
|
||||
if (hideIndicator) {
|
||||
@@ -695,95 +697,6 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
|
||||
onDragFinish() {
|
||||
for (const item of this.dragShiftableItems) {
|
||||
item.style.transform = '';
|
||||
}
|
||||
delete this._topToNormalTabs;
|
||||
for (const item of gBrowser.tabContainer.ariaFocusableItems) {
|
||||
if (gBrowser.isTab(item)) {
|
||||
let isVisible = true;
|
||||
let parent = item.group;
|
||||
while (parent) {
|
||||
if (!parent.visible) {
|
||||
isVisible = false;
|
||||
break;
|
||||
}
|
||||
parent = parent.group;
|
||||
}
|
||||
if (!isVisible) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const itemToAnimate =
|
||||
item.group?.hasAttribute('split-view-group') || gBrowser.isTabGroupLabel(item)
|
||||
? item.group
|
||||
: item;
|
||||
itemToAnimate.style.removeProperty('--zen-folder-indent');
|
||||
}
|
||||
this.removeTabContainersDragoverClass();
|
||||
}
|
||||
|
||||
get dragShiftableItems() {
|
||||
const separator = gZenWorkspaces.pinnedTabsContainer.querySelector(
|
||||
'.pinned-tabs-container-separator'
|
||||
);
|
||||
// Make sure to always return the separator at the start of the array
|
||||
return Services.prefs.getBoolPref('zen.view.show-newtab-button-top')
|
||||
? [separator, gZenWorkspaces.activeWorkspaceElement.newTabButton]
|
||||
: [separator];
|
||||
}
|
||||
|
||||
animateSeparatorMove(movingTabs, dropElement, isPinned) {
|
||||
let draggedTab = movingTabs[0];
|
||||
if (gBrowser.isTabGroupLabel(draggedTab) && draggedTab.group.isZenFolder) {
|
||||
this._isGoingToPinnedTabs = true;
|
||||
return;
|
||||
}
|
||||
if (draggedTab?.group?.hasAttribute('split-view-group')) {
|
||||
draggedTab = draggedTab.group;
|
||||
}
|
||||
const itemsToCheck = this.dragShiftableItems;
|
||||
let translate = movingTabs[isPinned ? movingTabs.length - 1 : 0].getBoundingClientRect().top;
|
||||
if (isPinned) {
|
||||
const rect = draggedTab.getBoundingClientRect();
|
||||
translate += rect.height;
|
||||
}
|
||||
const draggingTabHeight = movingTabs.reduce((acc, item) => {
|
||||
return acc + window.windowUtils.getBoundsWithoutFlushing(item).height;
|
||||
}, 0);
|
||||
if (typeof this._topToNormalTabs === 'undefined') {
|
||||
const rects = itemsToCheck.map((item) => window.windowUtils.getBoundsWithoutFlushing(item));
|
||||
this._topToNormalTabs = rects[0].top + rects.at(-1).height / (isPinned ? 2 : 4);
|
||||
}
|
||||
let topToNormalTabs = this._topToNormalTabs;
|
||||
const isGoingToPinnedTabs =
|
||||
translate < topToNormalTabs && gBrowser.pinnedTabCount - gBrowser._numZenEssentials > 0;
|
||||
const multiplier = isGoingToPinnedTabs !== isPinned ? (isGoingToPinnedTabs ? 1 : -1) : 0;
|
||||
this._isGoingToPinnedTabs = isGoingToPinnedTabs;
|
||||
if (!dropElement) {
|
||||
itemsToCheck.forEach((item) => {
|
||||
item.style.transform = `translateY(${draggingTabHeight * multiplier}px)`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getLastTabBound(lastBound, lastTab, isDraggingFolder = false) {
|
||||
if (!lastTab.pinned || isDraggingFolder) {
|
||||
return lastBound;
|
||||
}
|
||||
const shiftedItems = this.dragShiftableItems;
|
||||
let totalHeight = shiftedItems.reduce((acc, item) => {
|
||||
return acc + window.windowUtils.getBoundsWithoutFlushing(item).height;
|
||||
}, 0);
|
||||
if (shiftedItems.length === 1) {
|
||||
// Means the new tab button is not at the top or not visible
|
||||
const lastTabRect = window.windowUtils.getBoundsWithoutFlushing(lastTab);
|
||||
totalHeight += lastTabRect.height;
|
||||
}
|
||||
return lastBound + totalHeight + 6;
|
||||
}
|
||||
|
||||
get dragIndicator() {
|
||||
if (!this._dragIndicator) {
|
||||
this._dragIndicator = document.createElement('div');
|
||||
|
||||
@@ -715,7 +715,6 @@
|
||||
}
|
||||
|
||||
& .zen-essentials-container {
|
||||
will-change: transform;
|
||||
justify-content: center;
|
||||
grid-template-columns: 1fr !important;
|
||||
padding: 0 !important;
|
||||
@@ -1108,8 +1107,6 @@
|
||||
}
|
||||
|
||||
.zen-essentials-container {
|
||||
will-change: transform;
|
||||
|
||||
overflow: hidden;
|
||||
gap: 4px;
|
||||
transition:
|
||||
@@ -1166,7 +1163,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.zen-essentials-container > .tabbrowser-tab,
|
||||
.tabbrowser-tab[zen-essential='true'],
|
||||
#zen-welcome-initial-essentials-browser-sidebar-essentials .tabbrowser-tab {
|
||||
--toolbarbutton-inner-padding: 0;
|
||||
max-width: unset;
|
||||
@@ -1288,9 +1285,9 @@
|
||||
width: calc(var(--indicator-width) - 2 * var(--zen-drag-indicator-height) - 4px);
|
||||
height: var(--zen-drag-indicator-height);
|
||||
transition:
|
||||
top 0.1s ease-out,
|
||||
left 0.1s ease-out,
|
||||
width 0.1s ease-out;
|
||||
top 0.05s ease-out,
|
||||
left 0.05s ease-out,
|
||||
width 0.05s ease-out;
|
||||
|
||||
&::before {
|
||||
left: calc(-2 * var(--zen-drag-indicator-height));
|
||||
@@ -1373,7 +1370,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tabbrowser-tab[zen-dragtarget],
|
||||
.tab-group-label-container[zen-dragtarget] {
|
||||
z-index: 9 !important;
|
||||
/* Drag and drop */
|
||||
|
||||
#zen-dragover-background {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
/* Extra width to cover the sidebar splitter */
|
||||
width: calc(100% + var(--zen-toolbox-padding));
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
background: var(--zen-primary-color);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ export class nsZenWorkspace extends MozXULElement {
|
||||
|
||||
static get markup() {
|
||||
return `
|
||||
<vbox class="zen-workspace-tabs-section zen-current-workspace-indicator" flex="1" context="zenWorkspaceMoreActions">
|
||||
<vbox class="zen-workspace-tabs-section zen-current-workspace-indicator zen-drop-target" flex="1" context="zenWorkspaceMoreActions">
|
||||
<stack class="zen-current-workspace-indicator-stack">
|
||||
<image class="zen-current-workspace-indicator-chevron" />
|
||||
<hbox class="zen-current-workspace-indicator-icon" />
|
||||
|
||||
@@ -1568,11 +1568,7 @@ class nsZenWorkspaces {
|
||||
}
|
||||
|
||||
async changeWorkspace(workspace, ...args) {
|
||||
if (
|
||||
!this.workspaceEnabled ||
|
||||
this.#inChangingWorkspace ||
|
||||
gNavToolbox.hasAttribute('movingtab')
|
||||
) {
|
||||
if (!this.workspaceEnabled || this.#inChangingWorkspace) {
|
||||
return;
|
||||
}
|
||||
this.#inChangingWorkspace = true;
|
||||
@@ -2433,7 +2429,7 @@ class nsZenWorkspaces {
|
||||
return workspaceData;
|
||||
}
|
||||
|
||||
async updateTabsContainers(target = undefined, forAnimation = false) {
|
||||
updateTabsContainers(target = undefined, forAnimation = false) {
|
||||
this.makeSureEmptyTabIsFirst();
|
||||
if (target && !target.target?.parentNode) {
|
||||
target = null;
|
||||
@@ -2443,7 +2439,7 @@ class nsZenWorkspaces {
|
||||
if (target?.type === 'TabClose' || target?.type === 'TabOpen') {
|
||||
animateContainer = target.target.pinned;
|
||||
}
|
||||
await this.onPinnedTabsResize(
|
||||
this.onPinnedTabsResize(
|
||||
// This is what happens when we join a resize observer, an event listener
|
||||
// while using it as a method.
|
||||
[{ target: (target?.target ? target.target : target) ?? this.pinnedTabsContainer }],
|
||||
@@ -2491,7 +2487,7 @@ class nsZenWorkspaces {
|
||||
}
|
||||
}
|
||||
|
||||
async onPinnedTabsResize(entries, forAnimation = false, animateContainer = false) {
|
||||
onPinnedTabsResize(entries, forAnimation = false, animateContainer = false) {
|
||||
if (
|
||||
document.documentElement.hasAttribute('inDOMFullscreen') ||
|
||||
!this._hasInitializedTabsStrip ||
|
||||
@@ -2515,9 +2511,7 @@ class nsZenWorkspaces {
|
||||
// Get all workspaces that have the same userContextId
|
||||
const activeWorkspace = this.getActiveWorkspace();
|
||||
const userContextId = activeWorkspace.containerTabId;
|
||||
const workspaces = this._workspaceCache.filter(
|
||||
(w) => w.containerTabId === userContextId && w.uuid !== originalWorkspaceId
|
||||
);
|
||||
const workspaces = this.getWorkspaces().filter((w) => w.containerTabId === userContextId);
|
||||
workspacesIds.push(...workspaces.map((w) => w.uuid));
|
||||
} else {
|
||||
workspacesIds.push(originalWorkspaceId);
|
||||
@@ -2690,7 +2684,7 @@ class nsZenWorkspaces {
|
||||
return tab;
|
||||
}
|
||||
|
||||
async changeWorkspaceShortcut(offset = 1, whileScrolling = false) {
|
||||
async changeWorkspaceShortcut(offset = 1, whileScrolling = false, disableWrap = false) {
|
||||
// Cycle through workspaces
|
||||
let workspaces = this.getWorkspaces();
|
||||
let activeWorkspace = this.getActiveWorkspace();
|
||||
@@ -2698,7 +2692,7 @@ class nsZenWorkspaces {
|
||||
|
||||
// note: offset can be negative
|
||||
let targetIndex = workspaceIndex + offset;
|
||||
if (this.shouldWrapAroundNavigation) {
|
||||
if (this.shouldWrapAroundNavigation && !disableWrap) {
|
||||
// Add length to handle negative indices and loop
|
||||
targetIndex = (targetIndex + workspaces.length) % workspaces.length;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user