feat: Make sure to sync tab's permanent key to other windows, b=bug #11750, c=folders, split-view

This commit is contained in:
mr. m
2026-01-01 17:43:57 +01:00
parent 5fb096865c
commit f6ba087539
8 changed files with 56 additions and 19 deletions

View File

@@ -6,7 +6,7 @@
value: true value: true
- name: zen.folders.search.hover-delay - name: zen.folders.search.hover-delay
value: 900 # ms value: 700 # ms
- name: zen.folders.max-subfolders - name: zen.folders.max-subfolders
value: 5 value: 5

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/sessionstore/SessionStartup.sys.mjs b/browser/components/sessionstore/SessionStartup.sys.mjs diff --git a/browser/components/sessionstore/SessionStartup.sys.mjs b/browser/components/sessionstore/SessionStartup.sys.mjs
index be23213ae9ec7e59358a17276c6c3764d38d9996..229bb1346f9349892acb1e9e05109b28f5a5b45f 100644 index be23213ae9ec7e59358a17276c6c3764d38d9996..c7bb413d7e2d8ce3f9bc38a925d57e59d882111d 100644
--- a/browser/components/sessionstore/SessionStartup.sys.mjs --- a/browser/components/sessionstore/SessionStartup.sys.mjs
+++ b/browser/components/sessionstore/SessionStartup.sys.mjs +++ b/browser/components/sessionstore/SessionStartup.sys.mjs
@@ -40,6 +40,7 @@ ChromeUtils.defineESModuleGetters(lazy, { @@ -40,6 +40,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
@@ -19,16 +19,17 @@ index be23213ae9ec7e59358a17276c6c3764d38d9996..229bb1346f9349892acb1e9e05109b28
this._initialized = true; this._initialized = true;
gOnceInitializedDeferred.resolve(); gOnceInitializedDeferred.resolve();
return; return;
@@ -179,6 +180,8 @@ export var SessionStartup = { @@ -179,6 +180,9 @@ export var SessionStartup = {
this._initialState = parsed; this._initialState = parsed;
} }
+ this._initialState ||= {};
+ lazy.ZenSessionStore.onFileRead(this._initialState); + lazy.ZenSessionStore.onFileRead(this._initialState);
+ +
if (this._initialState == null) { if (this._initialState == null) {
// No valid session found. // No valid session found.
this._sessionType = this.NO_SESSION; this._sessionType = this.NO_SESSION;
@@ -335,12 +338,7 @@ export var SessionStartup = { @@ -335,12 +339,7 @@ export var SessionStartup = {
isAutomaticRestoreEnabled() { isAutomaticRestoreEnabled() {
if (this._resumeSessionEnabled === null) { if (this._resumeSessionEnabled === null) {
this._resumeSessionEnabled = this._resumeSessionEnabled =

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 diff --git a/browser/components/tabbrowser/content/drag-and-drop.js b/browser/components/tabbrowser/content/drag-and-drop.js
index 97b931c3c7385a52d20204369fcf6d6999053687..4ac61b298ac64332afb6eac9918fe3eb7ba789ad 100644 index 97b931c3c7385a52d20204369fcf6d6999053687..bd64a97046d2a62e842cc922764ad129da99905f 100644
--- a/browser/components/tabbrowser/content/drag-and-drop.js --- a/browser/components/tabbrowser/content/drag-and-drop.js
+++ b/browser/components/tabbrowser/content/drag-and-drop.js +++ b/browser/components/tabbrowser/content/drag-and-drop.js
@@ -32,6 +32,9 @@ @@ -32,6 +32,9 @@
@@ -221,7 +221,23 @@ index 97b931c3c7385a52d20204369fcf6d6999053687..4ac61b298ac64332afb6eac9918fe3eb
let isPinned = tab.pinned; let isPinned = tab.pinned;
let numPinned = gBrowser.pinnedTabCount; let numPinned = gBrowser.pinnedTabCount;
let allTabs = this._tabbrowserTabs.ariaFocusableItems; let allTabs = this._tabbrowserTabs.ariaFocusableItems;
@@ -2457,17 +2489,14 @@ @@ -1598,7 +1630,6 @@
for (let item of this._tabbrowserTabs.ariaFocusableItems) {
item = elementToMove(item);
- item.style.transform = "";
item.removeAttribute("multiselected-move-together");
delete item._moveTogetherSelectedTabsData;
}
@@ -2426,7 +2457,6 @@
for (let item of this._tabbrowserTabs.ariaFocusableItems) {
this._resetGroupTarget(item);
item = elementToMove(item);
- item.style.transform = "";
}
this._tabbrowserTabs.removeAttribute("movingtab-group");
this._tabbrowserTabs.removeAttribute("movingtab-ungroup");
@@ -2457,17 +2487,14 @@
tab.style.left = ""; tab.style.left = "";
tab.style.top = ""; tab.style.top = "";
tab.style.maxWidth = ""; tab.style.maxWidth = "";

View File

@@ -80,7 +80,9 @@
init() { init() {
super.init(); super.init();
this.handle_windowDragEnter = this.handle_windowDragEnter.bind(this); this.handle_windowDragEnter = this.handle_windowDragEnter.bind(this);
window.addEventListener('dragleave', this.handle_windowDragLeave.bind(this), true); window.addEventListener('dragleave', this.handle_windowDragLeave.bind(this), {
capture: true,
});
} }
startTabDrag(event, tab, ...args) { startTabDrag(event, tab, ...args) {
@@ -640,14 +642,14 @@
if (!isTab(draggedTab)) { if (!isTab(draggedTab)) {
return; return;
} }
this.#maybeClearVerticalPinnedGridDragOver(draggedTab);
this.clearSpaceSwitchTimer();
const { clientX, clientY } = event; const { clientX, clientY } = event;
const { innerWidth, innerHeight } = window; const { innerWidth, innerHeight } = window;
const isOutOfWindow = const isOutOfWindow =
clientX < 0 || clientX > innerWidth || clientY < 0 || clientY > innerHeight; clientX < 0 || clientX > innerWidth || clientY < 0 || clientY > innerHeight;
if (isOutOfWindow && !this.#isOutOfWindow) { if (isOutOfWindow && !this.#isOutOfWindow) {
this.#isOutOfWindow = true; this.#isOutOfWindow = true;
this.#maybeClearVerticalPinnedGridDragOver(draggedTab);
this.clearSpaceSwitchTimer();
this.clearDragOverVisuals(); this.clearDragOverVisuals();
const dt = event.dataTransfer; const dt = event.dataTransfer;
let dragData = draggedTab._dragData; let dragData = draggedTab._dragData;
@@ -717,6 +719,10 @@
return; return;
} }
this.#isAnimatingTabMove = true; this.#isAnimatingTabMove = true;
for (let item of this._tabbrowserTabs.ariaFocusableItems) {
item = elementToMove(item);
item.style.transform = '';
}
const animateElement = (ele, translateY) => { const animateElement = (ele, translateY) => {
ele.style.transform = `translateY(${translateY}px)`; ele.style.transform = `translateY(${translateY}px)`;
setTimeout(() => { setTimeout(() => {

View File

@@ -686,7 +686,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
const position = isRightSide ? 'topleft topright' : 'topright topleft'; const position = isRightSide ? 'topleft topright' : 'topright topleft';
return { return {
position: position, position: position,
x: 5, x: 10,
y: -25, y: -25,
}; };
} }

View File

@@ -156,24 +156,25 @@ export class nsZenSessionManager {
...this.#sidebar, ...this.#sidebar,
spaces: this._migrationData?.spaces || [], spaces: this._migrationData?.spaces || [],
}; };
// There might be cases where there are no windows in the
// initial state, for example if the user had 'restore previous
// session' disabled before migration. In that case, we try
// to restore the last closed normal window.
if (!initialState.windows?.length) { if (!initialState.windows?.length) {
let normalClosedWindow = initialState._closedWindows?.find( let normalClosedWindow = initialState._closedWindows?.find(
(win) => !win.isPopup && !win.isTaskbarTab && !win.isPrivate (win) => !win.isPopup && !win.isTaskbarTab && !win.isPrivate
); );
if (normalClosedWindow) { if (normalClosedWindow) {
initialState.windows = [normalClosedWindow]; initialState.windows = [Cu.cloneInto(normalClosedWindow, {})];
this.log('Restoring tabs from last closed normal window'); this.log('Restoring tabs from last closed normal window');
} }
} }
for (const winData of initialState.windows || []) { for (const winData of initialState.windows || []) {
winData.spaces = this._migrationData?.spaces || []; winData.spaces = this._migrationData?.spaces || [];
} }
return; // Save the state to the sidebar object so that it gets written
} // to the session file.
// If there's no initial state, nothing to restore. This would this.saveState(initialState);
// happen if the file is empty or corrupted.
if (!initialState) {
this.log('No initial state to restore!');
return; return;
} }
// If there are no windows, we create an empty one. By default, // If there are no windows, we create an empty one. By default,

View File

@@ -296,10 +296,12 @@ class nsZenWindowSync {
if (!aTab.id) { if (!aTab.id) {
return; return;
} }
let permanentKey = aTab.linkedBrowser.permanentKey;
this.#runOnAllWindows(null, (win) => { this.#runOnAllWindows(null, (win) => {
const tab = this.#getItemFromWindow(win, aTab.id); const tab = this.#getItemFromWindow(win, aTab.id);
if (tab) { if (tab) {
tab.permanentKey = aTab.linkedBrowser.permanentKey; tab.linkedBrowser.permanentKey = permanentKey;
tab.permanentKey = permanentKey;
} }
}); });
} }
@@ -578,7 +580,16 @@ class nsZenWindowSync {
() => { () => {
this.log(`Swapping docshells between windows for tab ${aOurTab.id}`); this.log(`Swapping docshells between windows for tab ${aOurTab.id}`);
aOurTab.ownerGlobal.gBrowser.swapBrowsersAndCloseOther(aOurTab, aOtherTab, false); aOurTab.ownerGlobal.gBrowser.swapBrowsersAndCloseOther(aOurTab, aOtherTab, false);
this.#makeSureTabSyncsPermanentKey(aOurTab); // Sometimes, when closing a window for example, when we swap the browsers,
// there's a chance that the tab does not have the entries state moved over properly.
// To avoid losing history entries, we have to keep the permanentKey in sync.
this.#makeSureTabSyncsPermanentKey(aOtherTab);
// Since we are moving progress listeners around, there's a chance that we
// trigger a load while making the switch, and since we remove the previous
// tab's listeners, the other browser window will never get the 'finish load' event
// and will stay in a 'busy' state forever.
// To avoid this, we manually check if the other tab is still busy after the swap,
// and if not, we remove the busy attribute from our tab.
if (!aOtherTab.hasAttribute('busy')) { if (!aOtherTab.hasAttribute('busy')) {
aOurTab.removeAttribute('busy'); aOurTab.removeAttribute('busy');
} }

View File

@@ -260,6 +260,8 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
return; return;
} }
gBrowser.tabContainer.tabDragAndDrop.finishMoveTogetherSelectedTabs(draggedTab); gBrowser.tabContainer.tabDragAndDrop.finishMoveTogetherSelectedTabs(draggedTab);
} else {
return;
} }
if ( if (
!this._lastOpenedTab || !this._lastOpenedTab ||