fix: Fixed drag and drop not calculating window bounds correctly, b=closes #12156, closes https://github.com/zen-browser/desktop/issues/11582, closes https://github.com/zen-browser/desktop/issues/12204, c=tabs

This commit is contained in:
mr. m
2026-02-02 14:57:17 +01:00
parent bf96b512cb
commit 33846dbce0
4 changed files with 123 additions and 67 deletions

View File

@@ -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 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b1f2bf82b 100644
index 57800333445ec7850742145527e04ae8d504b0bb..a13875436a72f89178455a09c8665b9a1ef240b5 100644
--- a/browser/components/tabbrowser/content/drag-and-drop.js
+++ b/browser/components/tabbrowser/content/drag-and-drop.js
@@ -35,6 +35,9 @@
@@ -39,7 +39,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
event.stopPropagation();
+ if (draggedTab && dropEffect == "move") {
+ this.handle_drop_transition?.(draggedTab._dragData.dropElement, draggedTab, movingTabs, draggedTab._dragData.dropBefore);
+ gZenPinnedTabManager.moveToAnotherTabContainerIfNecessary(event, movingTabs);
+ gZenPinnedTabManager.moveToAnotherTabContainerIfNecessary(event, draggedTab, movingTabs, this._getDropIndex(event));
+ }
if (draggedTab && dropEffect == "copy") {
let duplicatedDraggedTab;
@@ -102,7 +102,36 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
postTransitionCleanup();
} else {
let onTransitionEnd = transitionendEvent => {
@@ -584,6 +597,7 @@
@@ -513,7 +526,7 @@
if (tab.selected) {
selectedTab = tab;
indexForSelectedTab = newIndex;
- } else {
+ } else if (false) {
const newTab = gBrowser.adoptTab(tab, {
elementIndex: newIndex,
selectTab: tab == draggedTab,
@@ -523,7 +536,7 @@
}
}
}
- if (selectedTab) {
+ if (false) {
const newTab = gBrowser.adoptTab(selectedTab, {
elementIndex: indexForSelectedTab,
selectTab: selectedTab == draggedTab,
@@ -534,10 +547,6 @@
}
// Restore tab selection
- gBrowser.addRangeToMultiSelectedTabs(
- this._tabbrowserTabs.dragAndDropElements[dropIndex],
- this._tabbrowserTabs.dragAndDropElements[newIndex - 1]
- );
} else {
// Pass true to disallow dropping javascript: or data: urls
let links;
@@ -584,6 +593,7 @@
let nextItem = this._tabbrowserTabs.dragAndDropElements[newIndex];
let tabGroup = isTab(nextItem) && nextItem.group;
@@ -110,7 +139,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
gBrowser.loadTabs(urls, {
inBackground,
replace,
@@ -621,7 +635,16 @@
@@ -621,7 +631,16 @@
this._expandGroupOnDrop(draggedTab);
}
this._resetTabsAfterDrop(draggedTab.ownerDocument);
@@ -128,7 +157,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
if (
dt.mozUserCancelled ||
dt.dropEffect != "none" ||
@@ -825,7 +848,10 @@
@@ -825,7 +844,10 @@
_getDragTarget(event, { ignoreSides = false } = {}) {
let { target } = event;
while (target) {
@@ -140,7 +169,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
break;
}
target = target.parentNode;
@@ -842,14 +868,17 @@
@@ -842,14 +864,17 @@
return null;
}
}
@@ -160,7 +189,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
!this._tabbrowserTabs.expandOnHover
);
}
@@ -880,7 +909,8 @@
@@ -880,7 +905,8 @@
isTabGroupLabel(draggedTab) &&
draggedTab._dragData?.expandGroupOnDrop
) {
@@ -170,7 +199,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
}
}
@@ -1058,7 +1088,6 @@
@@ -1058,7 +1084,6 @@
// using updateDragImage. On Linux, we can use a panel.
if (platform == "win" || platform == "macosx") {
captureListener = function () {
@@ -178,7 +207,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
};
} else {
// Create a panel to use it in setDragImage
@@ -1096,7 +1125,6 @@
@@ -1096,7 +1121,6 @@
);
dragImageOffset = dragImageOffset * scale;
}
@@ -186,7 +215,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
// _dragData.offsetX/Y give the coordinates that the mouse should be
// positioned relative to the corner of the new window created upon
@@ -1115,7 +1143,7 @@
@@ -1115,7 +1139,7 @@
let dropEffect = this.getDropEffectForTabDrag(event);
let isMovingInTabStrip = !fromTabList && dropEffect == "move";
let collapseTabGroupDuringDrag =
@@ -195,7 +224,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
tab._dragData = {
offsetX: this._tabbrowserTabs.verticalMode
@@ -1125,7 +1153,7 @@
@@ -1125,7 +1149,7 @@
? event.screenY - window.screenY - tabOffset
: event.screenY - window.screenY,
scrollPos:
@@ -204,7 +233,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
? this._tabbrowserTabs.pinnedTabsContainer.scrollPosition
: this._tabbrowserTabs.arrowScrollbox.scrollPosition,
screenX: event.screenX,
@@ -1152,6 +1180,7 @@
@@ -1152,6 +1176,7 @@
if (collapseTabGroupDuringDrag) {
tab.group.collapsed = true;
@@ -212,7 +241,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
}
}
}
@@ -1176,6 +1205,7 @@
@@ -1176,6 +1201,7 @@
if (tabStripItemElement.hasAttribute("dragtarget")) {
return;
}
@@ -220,7 +249,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
let isPinned = tab.pinned;
let numPinned = gBrowser.pinnedTabCount;
let dragAndDropElements = this._tabbrowserTabs.dragAndDropElements;
@@ -1601,7 +1631,6 @@
@@ -1601,7 +1627,6 @@
for (let item of this._tabbrowserTabs.dragAndDropElements) {
item = elementToMove(item);
@@ -228,7 +257,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
item.removeAttribute("multiselected-move-together");
delete item._moveTogetherSelectedTabsData;
}
@@ -2429,7 +2458,6 @@
@@ -2429,7 +2454,6 @@
for (let item of this._tabbrowserTabs.dragAndDropElements) {
this._resetGroupTarget(item);
item = elementToMove(item);
@@ -236,7 +265,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
}
this._tabbrowserTabs.removeAttribute("movingtab-group");
this._tabbrowserTabs.removeAttribute("movingtab-ungroup");
@@ -2460,17 +2488,14 @@
@@ -2460,17 +2484,14 @@
tab.style.left = "";
tab.style.top = "";
tab.style.maxWidth = "";

View File

@@ -672,16 +672,17 @@
if (!isTab(draggedTab)) {
return;
}
const { screenX, screenY } = event;
let { screenX, clientX, screenY, clientY } = event;
if (!screenX && !screenY) {
return;
}
const { innerWidth, innerHeight, screenX: windowScreenX, screenY: windowScreenY } = window;
const { innerWidth: winWidth, innerHeight: winHeight } = window;
let allowedMargin = Services.prefs.getIntPref("zen.tabs.dnd-outside-window-margin", 5);
const isOutOfWindow =
screenX < windowScreenX ||
screenX > windowScreenX + innerWidth ||
screenY < windowScreenY ||
screenY > windowScreenY + innerHeight;
clientX <= allowedMargin ||
clientX >= winWidth - allowedMargin ||
clientY <= allowedMargin ||
clientY >= winHeight - allowedMargin;
if (isOutOfWindow && !this.#isOutOfWindow) {
this.#isOutOfWindow = true;
gZenViewSplitter.onBrowserDragEndToSplit(event, true);
@@ -712,6 +713,8 @@
once: true,
capture: true,
});
} else {
this.#isOutOfWindow = false;
}
}
@@ -768,7 +771,8 @@
draggedTab.hasAttribute("zen-essential") ||
draggedTab.getAttribute("zen-workspace-id") != gZenWorkspaces.activeWorkspace ||
!dropElement.visible ||
!draggedTab.visible
!draggedTab.visible ||
draggedTab.ownerGlobal !== window
) {
return;
}
@@ -857,18 +861,19 @@
handle_dragend(event) {
const dt = event.dataTransfer;
const draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
let ownerGlobal = draggedTab?.ownerGlobal;
draggedTab.style.visibility = "";
let currentEssenialContainer = gZenWorkspaces.getCurrentEssentialsContainer();
let currentEssenialContainer = ownerGlobal.gZenWorkspaces.getCurrentEssentialsContainer();
if (currentEssenialContainer?.essentialsPromo) {
currentEssenialContainer.essentialsPromo.remove();
}
// We also call it here to ensure we clear any highlight if the drop happened
// outside of a valid drop target.
gZenFolders.highlightGroupOnDragOver(null);
ownerGlobal.gZenFolders.highlightGroupOnDragOver(null);
this.ZenDragAndDropService.onDragEnd();
super.handle_dragend(event);
this.#removeDragOverBackground();
gZenPinnedTabManager.removeTabContainersDragoverClass();
ownerGlobal.gZenPinnedTabManager.removeTabContainersDragoverClass();
this.#maybeClearVerticalPinnedGridDragOver();
this.originalDragImageArgs = [];
window.removeEventListener("dragover", this.handle_windowDragEnter, { capture: true });
@@ -881,9 +886,9 @@
this._tempDragImageParent.remove();
delete this._tempDragImageParent;
}
delete gZenCompactModeManager._isTabBeingDragged;
delete ownerGlobal.gZenCompactModeManager._isTabBeingDragged;
if (dt.dropEffect !== "move") {
gZenCompactModeManager._clearAllHoverStates();
ownerGlobal.gZenCompactModeManager._clearAllHoverStates();
}
}
@@ -1286,6 +1291,9 @@
return;
}
// eslint-disable-next-line mozilla/valid-services
Services.zen.playHapticFeedback();
dragData.animDropElementIndex = newIndex;
dragData.dropElement = tabs[Math.min(newIndex, tabs.length - 1)];
dragData.dropBefore = newIndex < tabs.length;

View File

@@ -236,6 +236,9 @@ class nsZenWindowSync {
if (tab.pinned && !tab._zenPinnedInitialState) {
await this.setPinnedTabState(tab);
}
if (!lazy.gWindowSyncEnabled) {
tab._zenContentsVisible = true;
}
}
});
}

View File

@@ -559,31 +559,50 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
}
// eslint-disable-next-line complexity
moveToAnotherTabContainerIfNecessary(event, movingTabs) {
moveToAnotherTabContainerIfNecessary(event, draggedTab, movingTabs, dropIndex) {
if (!this.enabled) {
return false;
}
movingTabs = movingTabs.map((tab) => {
let workspaceId;
if (tab.ownerGlobal !== window) {
if (
!tab.hasAttribute("zen-essential") &&
tab.getAttribute("zen-workspace-id") != gZenWorkspaces.activeWorkspace
) {
workspaceId = gZenWorkspaces.activeWorkspace;
tab.ownerGlobal.gBrowser.selectedTab = tab.ownerGlobal.gBrowser._findTabToBlurTo(
tab,
movingTabs
);
tab.ownerGlobal.gZenWorkspaces.moveTabToWorkspace(tab, workspaceId);
let newIndex = dropIndex;
let fromDifferentWindow = false;
movingTabs = Array.from(movingTabs)
.reverse()
.map((tab) => {
let workspaceId;
if (tab.ownerGlobal !== window) {
fromDifferentWindow = true;
if (
!tab.hasAttribute("zen-essential") &&
tab.getAttribute("zen-workspace-id") != gZenWorkspaces.activeWorkspace
) {
workspaceId = gZenWorkspaces.activeWorkspace;
tab.ownerGlobal.gBrowser.selectedTab = tab.ownerGlobal.gBrowser._findTabToBlurTo(
tab,
movingTabs
);
tab.ownerGlobal.gZenWorkspaces.moveTabToWorkspace(tab, workspaceId);
}
// Move the tabs into this window. To avoid multiple tab-switches in
// the original window, the selected tab should be adopted last.
tab = gBrowser.adoptTab(tab, {
elementIndex: newIndex,
selectTab: tab == draggedTab,
});
if (tab) {
++newIndex;
}
if (workspaceId) {
tab.setAttribute("zen-workspace-id", workspaceId);
}
}
tab = gBrowser.adoptTab(tab);
if (workspaceId) {
tab.setAttribute("zen-workspace-id", workspaceId);
}
}
return tab;
});
return tab;
});
if (fromDifferentWindow) {
gBrowser.addRangeToMultiSelectedTabs(
gBrowser.tabContainer.dragAndDropElements[dropIndex],
gBrowser.tabContainer.dragAndDropElements[newIndex - 1]
);
}
try {
const pinnedTabsTarget = event.target.closest(
":is(.zen-current-workspace-indicator, .zen-workspace-pinned-tabs-section)"
@@ -605,9 +624,9 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
// Remove group labels from the moving tabs and replace it
// with the sub tabs
for (let i = 0; i < movingTabs.length; i++) {
const draggedTab = movingTabs[i];
if (gBrowser.isTabGroupLabel(draggedTab)) {
const group = draggedTab.group;
const tab = movingTabs[i];
if (gBrowser.isTabGroupLabel(tab)) {
const group = tab.group;
// remove label and add sub tabs to moving tabs
if (group) {
movingTabs.splice(i, 1, ...group.tabs);
@@ -618,35 +637,32 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
let isVertical = this.expandedSidebarMode;
let moved = false;
let hasActuallyMoved;
for (const draggedTab of movingTabs) {
for (const tab of movingTabs) {
let isRegularTabs = false;
// Check for essentials container
if (essentialTabsTarget) {
if (
!draggedTab.hasAttribute("zen-essential") &&
!draggedTab?.group?.hasAttribute("split-view-group")
) {
if (!tab.hasAttribute("zen-essential") && !tab?.group?.hasAttribute("split-view-group")) {
moved = true;
isVertical = false;
hasActuallyMoved = this.addToEssentials(draggedTab);
hasActuallyMoved = this.addToEssentials(tab);
}
}
// Check for pinned tabs container
else if (pinnedTabsTarget) {
if (!draggedTab.pinned) {
gBrowser.pinTab(draggedTab);
} else if (draggedTab.hasAttribute("zen-essential")) {
this.removeEssentials(draggedTab, false);
if (!tab.pinned) {
gBrowser.pinTab(tab);
} else if (tab.hasAttribute("zen-essential")) {
this.removeEssentials(tab, false);
moved = true;
}
}
// Check for normal tabs container
else if (tabsTarget || event.target.id === "zen-tabs-wrapper") {
if (draggedTab.pinned && !draggedTab.hasAttribute("zen-essential")) {
gBrowser.unpinTab(draggedTab);
if (tab.pinned && !tab.hasAttribute("zen-essential")) {
gBrowser.unpinTab(tab);
isRegularTabs = true;
} else if (draggedTab.hasAttribute("zen-essential")) {
this.removeEssentials(draggedTab);
} else if (tab.hasAttribute("zen-essential")) {
this.removeEssentials(tab);
moved = true;
isRegularTabs = true;
}
@@ -687,7 +703,7 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
elementIndex++;
}
gBrowser.moveTabTo(draggedTab, {
gBrowser.moveTabTo(tab, {
elementIndex,
forceUngrouped: targetElem?.group?.collapsed !== false,
});