mirror of
https://github.com/zen-browser/desktop.git
synced 2026-08-11 17:25:17 +00:00
feat: Early support for unsynced windoiws, b=no-bug, c=workspaces
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186f0d2bce5 100644
|
||||
index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..a932324e780e3c86c504c8b7aa8d433b04ef78d6 100644
|
||||
--- a/browser/components/tabbrowser/content/tabbrowser.js
|
||||
+++ b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
@@ -386,6 +386,7 @@
|
||||
@@ -715,7 +715,17 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
if (this.tabs.length == 1) {
|
||||
return null;
|
||||
}
|
||||
@@ -6319,7 +6470,7 @@
|
||||
@@ -6213,7 +6364,8 @@
|
||||
AppConstants.BROWSER_CHROME_URL,
|
||||
"_blank",
|
||||
options,
|
||||
- aTab
|
||||
+ aTab,
|
||||
+ "zen-unsynced"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6319,7 +6471,7 @@
|
||||
* `true` if element is a `<tab-group>`
|
||||
*/
|
||||
isTabGroup(element) {
|
||||
@@ -724,7 +734,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6404,8 +6555,8 @@
|
||||
@@ -6404,8 +6556,8 @@
|
||||
}
|
||||
|
||||
// Don't allow mixing pinned and unpinned tabs.
|
||||
@@ -735,7 +745,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
} else {
|
||||
tabIndex = Math.max(tabIndex, this.pinnedTabCount);
|
||||
}
|
||||
@@ -6431,10 +6582,16 @@
|
||||
@@ -6431,10 +6583,16 @@
|
||||
this.#handleTabMove(
|
||||
element,
|
||||
() => {
|
||||
@@ -754,7 +764,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
if (neighbor && this.isTab(element) && tabIndex > element._tPos) {
|
||||
neighbor.after(element);
|
||||
} else {
|
||||
@@ -6492,23 +6649,28 @@
|
||||
@@ -6492,23 +6650,28 @@
|
||||
#moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) {
|
||||
if (this.isTabGroupLabel(targetElement)) {
|
||||
targetElement = targetElement.group;
|
||||
@@ -789,7 +799,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
} 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 +6683,34 @@
|
||||
@@ -6521,14 +6684,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.
|
||||
@@ -825,7 +835,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
element.pinned
|
||||
? this.tabContainer.pinnedTabsContainer
|
||||
: this.tabContainer;
|
||||
@@ -6537,7 +6719,7 @@
|
||||
@@ -6537,7 +6720,7 @@
|
||||
element,
|
||||
() => {
|
||||
if (moveBefore) {
|
||||
@@ -834,7 +844,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
} else if (targetElement) {
|
||||
targetElement.after(element);
|
||||
} else {
|
||||
@@ -6607,10 +6789,10 @@
|
||||
@@ -6607,10 +6790,10 @@
|
||||
* @param {TabMetricsContext} [metricsContext]
|
||||
*/
|
||||
moveTabToGroup(aTab, aGroup, metricsContext) {
|
||||
@@ -847,7 +857,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
return;
|
||||
}
|
||||
if (aTab.group && aTab.group.id === aGroup.id) {
|
||||
@@ -6656,6 +6838,7 @@
|
||||
@@ -6656,6 +6839,7 @@
|
||||
|
||||
let state = {
|
||||
tabIndex: tab._tPos,
|
||||
@@ -855,7 +865,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
};
|
||||
if (tab.visible) {
|
||||
state.elementIndex = tab.elementIndex;
|
||||
@@ -6682,7 +6865,7 @@
|
||||
@@ -6682,7 +6866,7 @@
|
||||
let changedTabGroup =
|
||||
previousTabState.tabGroupId != currentTabState.tabGroupId;
|
||||
|
||||
@@ -864,7 +874,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
tab.dispatchEvent(
|
||||
new CustomEvent("TabMove", {
|
||||
bubbles: true,
|
||||
@@ -6723,6 +6906,10 @@
|
||||
@@ -6723,6 +6907,10 @@
|
||||
|
||||
moveActionCallback();
|
||||
|
||||
@@ -875,7 +885,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
// Clear tabs cache after moving nodes because the order of tabs may have
|
||||
// changed.
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
@@ -7623,7 +7810,7 @@
|
||||
@@ -7623,7 +7811,7 @@
|
||||
// preventDefault(). It will still raise the window if appropriate.
|
||||
break;
|
||||
}
|
||||
@@ -884,7 +894,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
window.focus();
|
||||
aEvent.preventDefault();
|
||||
break;
|
||||
@@ -7640,7 +7827,6 @@
|
||||
@@ -7640,7 +7828,6 @@
|
||||
}
|
||||
case "TabGroupCollapse":
|
||||
aEvent.target.tabs.forEach(tab => {
|
||||
@@ -892,7 +902,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
});
|
||||
break;
|
||||
case "TabGroupCreateByUser":
|
||||
@@ -8589,6 +8775,7 @@
|
||||
@@ -8589,6 +8776,7 @@
|
||||
aWebProgress.isTopLevel
|
||||
) {
|
||||
this.mTab.setAttribute("busy", "true");
|
||||
@@ -900,7 +910,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..3acfbc6d434340f0a629eec7edd9e186
|
||||
gBrowser._tabAttrModified(this.mTab, ["busy"]);
|
||||
this.mTab._notselectedsinceload = !this.mTab.selected;
|
||||
}
|
||||
@@ -9623,7 +9810,7 @@ var TabContextMenu = {
|
||||
@@ -9623,7 +9811,7 @@ var TabContextMenu = {
|
||||
);
|
||||
contextUnpinSelectedTabs.hidden =
|
||||
!this.contextTab.pinned || !this.multiselected;
|
||||
|
||||
22
src/docshell/base/BrowsingContextWebProgress-cpp.patch
Normal file
22
src/docshell/base/BrowsingContextWebProgress-cpp.patch
Normal file
@@ -0,0 +1,22 @@
|
||||
diff --git a/docshell/base/BrowsingContextWebProgress.cpp b/docshell/base/BrowsingContextWebProgress.cpp
|
||||
index cc5bf6de7bf4875acf0c572549dc30ff06ac7f6f..4e0f3648f551fe9507a654d19f0a99e455418aa9 100644
|
||||
--- a/docshell/base/BrowsingContextWebProgress.cpp
|
||||
+++ b/docshell/base/BrowsingContextWebProgress.cpp
|
||||
@@ -54,7 +54,7 @@ NS_IMETHODIMP BrowsingContextWebProgress::AddProgressListener(
|
||||
|
||||
if (mListenerInfoList.Contains(listener)) {
|
||||
// The listener is already registered!
|
||||
- return NS_ERROR_FAILURE;
|
||||
+ return NS_OK;
|
||||
}
|
||||
|
||||
mListenerInfoList.AppendElement(ListenerInfo(listener, aNotifyMask));
|
||||
@@ -68,7 +68,7 @@ NS_IMETHODIMP BrowsingContextWebProgress::RemoveProgressListener(
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
- return mListenerInfoList.RemoveElement(listener) ? NS_OK : NS_ERROR_FAILURE;
|
||||
+ return mListenerInfoList.RemoveElement(listener) ? NS_OK : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP BrowsingContextWebProgress::GetBrowsingContextXPCOM(
|
||||
@@ -145,13 +145,19 @@ class nsZenSessionManager {
|
||||
}
|
||||
|
||||
restoreNewWindow(aWindow, SessionStoreInternal) {
|
||||
if (aWindow.gZenWorkspaces?.privateWindowOrDisabled) {
|
||||
return;
|
||||
}
|
||||
lazy.SessionSaver.run().then(() => {
|
||||
const state = lazy.SessionStore.getCurrentState(true);
|
||||
const windows = state.windows || {};
|
||||
let newWindow = Cu.cloneInto(windows[0], {});
|
||||
delete newWindow.selected;
|
||||
const newState = { windows: [newWindow] };
|
||||
//SessionStoreInternal.restoreWindows(aWindow, newState, {});
|
||||
aWindow._zenRestorePromise = new Promise((resolve) => {
|
||||
SessionStoreInternal.restoreWindows(aWindow, newState, {});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,12 @@ class nsZenWindowSync {
|
||||
#browserWindows = {
|
||||
*[Symbol.iterator]() {
|
||||
for (let window of lazy.BrowserWindowTracker.orderedWindows) {
|
||||
if (window.__SSi && !window.closed && window.gZenStartup.isReady) {
|
||||
if (
|
||||
window.__SSi &&
|
||||
!window.closed &&
|
||||
window.gZenStartup.isReady &&
|
||||
!window.gZenWorkspaces?.privateWindowOrDisabled
|
||||
) {
|
||||
yield window;
|
||||
}
|
||||
}
|
||||
@@ -109,9 +114,23 @@ class nsZenWindowSync {
|
||||
* @param {Window} aWindow - The browser window that is about to be shown.
|
||||
*/
|
||||
#onWindowBeforeShow(aWindow) {
|
||||
// There are 2 possibilities to know if we are trying to open
|
||||
// a new *unsynced* window:
|
||||
// 1. We are passing `zen-unsynced` in the window arguments.
|
||||
// 2. We are trying to open a link in a new window where other synced
|
||||
// windows already exist
|
||||
if (
|
||||
aWindow.arguments.some((arg) => arg === 'zen-unsynced') ||
|
||||
(typeof aWindow.arguments[0] === 'string' &&
|
||||
aWindow.arguments.length > 1 &&
|
||||
[...this.#browserWindows].length > 0)
|
||||
) {
|
||||
aWindow.document.documentElement.setAttribute('zen-unsynced-window', 'true');
|
||||
return;
|
||||
}
|
||||
aWindow.gZenWindowSync = this;
|
||||
for (let eventName of EVENTS) {
|
||||
aWindow.addEventListener(eventName, this);
|
||||
aWindow.addEventListener(eventName, this, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +193,7 @@ class nsZenWindowSync {
|
||||
|
||||
handleEvent(aEvent) {
|
||||
const window = aEvent.currentTarget.ownerGlobal;
|
||||
if (!window.gZenStartup.isReady) {
|
||||
if (!window.gZenStartup.isReady || window.gZenWorkspaces?.privateWindowOrDisabled) {
|
||||
return;
|
||||
}
|
||||
if (this.#eventHandlingContext.window && this.#eventHandlingContext.window !== window) {
|
||||
@@ -619,7 +638,13 @@ class nsZenWindowSync {
|
||||
this.onTabSwitchOrWindowFocus(aEvent.target.ownerGlobal, previousTab);
|
||||
}
|
||||
|
||||
on_unload() {}
|
||||
on_unload(aEvent) {
|
||||
const window = aEvent.target.ownerGlobal;
|
||||
for (let eventName of EVENTS) {
|
||||
window.removeEventListener(eventName, this);
|
||||
}
|
||||
delete window.gZenWindowSync;
|
||||
}
|
||||
|
||||
on_TabGroupCreate(aEvent) {
|
||||
const tabGroup = aEvent.target;
|
||||
|
||||
@@ -55,6 +55,7 @@ class nsZenWorkspaces extends nsZenMultiWindowFeature {
|
||||
this.promiseDBInitialized,
|
||||
this.promisePinnedInitialized,
|
||||
SessionStore.promiseAllWindowsRestored,
|
||||
window._zenRestorePromise,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -835,8 +836,12 @@ class nsZenWorkspaces extends nsZenMultiWindowFeature {
|
||||
return PrivateBrowsingUtils.isWindowPrivate(window);
|
||||
}
|
||||
|
||||
get currentWindowIsSyncing() {
|
||||
return !document.documentElement.hasAttribute('zen-unsynced-window') && !this.isPrivateWindow;
|
||||
}
|
||||
|
||||
get privateWindowOrDisabled() {
|
||||
return this.isPrivateWindow || !this.shouldHaveWorkspaces;
|
||||
return !this.shouldHaveWorkspaces || !this.currentWindowIsSyncing;
|
||||
}
|
||||
|
||||
get workspaceEnabled() {
|
||||
@@ -865,12 +870,12 @@ class nsZenWorkspaces extends nsZenMultiWindowFeature {
|
||||
return this._workspaceCache;
|
||||
}
|
||||
|
||||
if (this.isPrivateWindow) {
|
||||
if (!this.currentWindowIsSyncing) {
|
||||
this._workspaceCache = {
|
||||
workspaces: this._privateWorkspace ? [this._privateWorkspace] : [],
|
||||
workspaces: this._tempWorkspace ? [this._tempWorkspace] : [],
|
||||
lastChangeTimestamp: 0,
|
||||
};
|
||||
this._activeWorkspace = this._privateWorkspace?.uuid;
|
||||
this._activeWorkspace = this._tempWorkspace?.uuid;
|
||||
return this._workspaceCache;
|
||||
}
|
||||
|
||||
@@ -1111,7 +1116,9 @@ class nsZenWorkspaces extends nsZenMultiWindowFeature {
|
||||
|
||||
shouldCloseWindow() {
|
||||
return (
|
||||
!window.toolbar.visible || Services.prefs.getBoolPref('browser.tabs.closeWindowWithLastTab')
|
||||
!window.toolbar.visible ||
|
||||
Services.prefs.getBoolPref('browser.tabs.closeWindowWithLastTab') ||
|
||||
this.privateWindowOrDisabled
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1388,7 +1395,7 @@ class nsZenWorkspaces extends nsZenMultiWindowFeature {
|
||||
}
|
||||
|
||||
async _propagateWorkspaceData({ ignoreStrip = false, clearCache = true, onInit = false } = {}) {
|
||||
const currentWindowIsPrivate = this.isPrivateWindow;
|
||||
const currentWindowIsPrivate = !this.currentWindowIsSyncing;
|
||||
if (onInit) {
|
||||
if (currentWindowIsPrivate) return;
|
||||
return await this._propagateWorkspaceDataForWindow(this.ownerWindow, {
|
||||
@@ -1401,7 +1408,7 @@ class nsZenWorkspaces extends nsZenMultiWindowFeature {
|
||||
// For example, when the window is in private browsing mode.
|
||||
if (
|
||||
!browser.gZenWorkspaces.workspaceEnabled ||
|
||||
browser.gZenWorkspaces.isPrivateWindow !== currentWindowIsPrivate
|
||||
!browser.gZenWorkspaces.currentWindowIsSyncing !== currentWindowIsPrivate
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -2450,8 +2457,8 @@ class nsZenWorkspaces extends nsZenMultiWindowFeature {
|
||||
if (!this.workspaceEnabled) {
|
||||
return;
|
||||
}
|
||||
if (this.isPrivateWindow) {
|
||||
name = 'Private ' + name;
|
||||
if (!this.currentWindowIsSyncing) {
|
||||
name = this.isPrivateWindow ? 'Private ' + name : gZenUIManager.generateUuidv4();
|
||||
}
|
||||
// get extra tabs remaning (e.g. on new profiles) and just move them to the new workspace
|
||||
const extraTabs = Array.from(gBrowser.tabContainer.arrowScrollbox.children).filter(
|
||||
@@ -2468,8 +2475,8 @@ class nsZenWorkspaces extends nsZenMultiWindowFeature {
|
||||
!dontChange,
|
||||
containerTabId
|
||||
);
|
||||
if (this.isPrivateWindow) {
|
||||
this._privateWorkspace = workspaceData;
|
||||
if (!this.currentWindowIsSyncing) {
|
||||
this._tempWorkspace = workspaceData;
|
||||
} else {
|
||||
await this.saveWorkspace(workspaceData, dontChange);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user