no-bug: Add alt+click for splitting tabs and other polishing details (gh-13308)

This commit is contained in:
mr. m
2026-04-19 00:38:23 +02:00
committed by GitHub
parent 2700722a1e
commit 3d14e98c76
20 changed files with 263 additions and 199 deletions

View File

@@ -58,6 +58,7 @@ zen-pinned-tab-replaced = Pinned tab URL has been replaced with the current URL!
zen-tabs-renamed = Tab has been successfully renamed!
zen-background-tab-opened-toast = New background tab opened!
zen-workspace-renamed-toast = Workspace has been successfully renamed!
zen-split-view-limit-toast = Can't add more panels to the split view!
zen-toggle-compact-mode-button =
.label = Compact Mode

View File

@@ -6,7 +6,7 @@ tab-zen-split-tabs =
.label =
{ $tabCount ->
[-1] Split out tab
[1] Join Tab (multiple selected tabs needed)
[1] Add split view...
*[other] Join { $tabCount } Tabs
}
.accesskey = S

View File

@@ -18,4 +18,4 @@
value: 300 # in milliseconds
- name: zen.glance.deactivate-docshell-during-animation
value: true
value: false

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tab.js b/browser/components/tabbrowser/content/tab.js
index 2e02bad1a7c89b4c3b5aee1e14c13bb953a64eb6..439766a40df5632ad790ab54a0c6af78a831e8ee 100644
index 2e02bad1a7c89b4c3b5aee1e14c13bb953a64eb6..3ac8d2facb224ae39d2199f2c5ec08b77e0c1dfd 100644
--- a/browser/components/tabbrowser/content/tab.js
+++ b/browser/components/tabbrowser/content/tab.js
@@ -21,6 +21,7 @@
@@ -151,7 +151,18 @@ index 2e02bad1a7c89b4c3b5aee1e14c13bb953a64eb6..439766a40df5632ad790ab54a0c6af78
on_click(event) {
if (event.button != 0) {
return;
@@ -620,11 +659,12 @@
@@ -617,14 +656,23 @@
trigger: "alt_click",
});
}
+ if (
+ !event.target.classList.contains("tab-close-button") &&
+ !event.target.classList.contains("tab-icon-overlay") &&
+ !event.target.classList.contains("tab-audio-button") &&
+ !this.splitView
+ ) {
+ gZenViewSplitter.contextSplitTabs(this);
+ }
return;
}
@@ -165,7 +176,7 @@ index 2e02bad1a7c89b4c3b5aee1e14c13bb953a64eb6..439766a40df5632ad790ab54a0c6af78
gBrowser.multiSelectedTabsCount > 0 &&
!event.target.classList.contains("tab-close-button") &&
!event.target.classList.contains("tab-icon-overlay") &&
@@ -636,8 +676,9 @@
@@ -636,8 +684,9 @@
}
if (
@@ -177,7 +188,7 @@ index 2e02bad1a7c89b4c3b5aee1e14c13bb953a64eb6..439766a40df5632ad790ab54a0c6af78
) {
if (this.activeMediaBlocked) {
if (this.multiselected) {
@@ -655,7 +696,7 @@
@@ -655,7 +704,7 @@
return;
}
@@ -186,7 +197,7 @@ index 2e02bad1a7c89b4c3b5aee1e14c13bb953a64eb6..439766a40df5632ad790ab54a0c6af78
if (this.multiselected) {
gBrowser.removeMultiSelectedTabs(
lazy.TabMetrics.userTriggeredContext(
@@ -675,6 +716,14 @@
@@ -675,6 +724,14 @@
// (see tabbrowser-tabs 'click' handler).
gBrowser.tabContainer._blockDblClick = true;
}
@@ -201,7 +212,7 @@ index 2e02bad1a7c89b4c3b5aee1e14c13bb953a64eb6..439766a40df5632ad790ab54a0c6af78
}
on_dblclick(event) {
@@ -698,6 +747,8 @@
@@ -698,6 +755,8 @@
animate: true,
triggeringEvent: event,
});

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25b964ccbb 100644
index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..2e1151dd1ac42b01529e746ee3b45c35e66ff55a 100644
--- a/browser/components/tabbrowser/content/tabbrowser.js
+++ b/browser/components/tabbrowser/content/tabbrowser.js
@@ -413,6 +413,7 @@
@@ -587,7 +587,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
} catch (e) {
console.error(e);
}
@@ -5603,6 +5757,13 @@
@@ -5603,6 +5757,14 @@
return;
}
@@ -597,11 +597,12 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
+ this.selectedTab = newTab;
+ }
+ }
+ animate &&= !aTab.splitView;
+
let isVisibleTab = aTab.visible;
// We have to sample the tab width now, since _beginRemoveTab might
// end up modifying the DOM in such a way that aTab gets a new
@@ -5610,6 +5771,9 @@
@@ -5610,6 +5772,9 @@
// state).
let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width;
let isLastTab = this.#isLastTabInWindow(aTab);
@@ -611,7 +612,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
if (
!this._beginRemoveTab(aTab, {
closeWindowFastpath: true,
@@ -5621,13 +5785,14 @@
@@ -5621,13 +5786,14 @@
telemetrySource,
})
) {
@@ -627,7 +628,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
let lockTabSizing =
!this.tabContainer.verticalMode &&
!aTab.pinned &&
@@ -5658,7 +5823,13 @@
@@ -5658,7 +5824,13 @@
// We're not animating, so we can cancel the animation stopwatch.
Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId);
aTab._closeTimeAnimTimerId = null;
@@ -642,7 +643,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
return;
}
@@ -5792,7 +5963,7 @@
@@ -5792,7 +5964,7 @@
closeWindowWithLastTab != null
? closeWindowWithLastTab
: !window.toolbar.visible ||
@@ -651,7 +652,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
if (closeWindow) {
// We've already called beforeunload on all the relevant tabs if we get here,
@@ -5816,6 +5987,7 @@
@@ -5816,6 +5988,7 @@
newTab = true;
}
@@ -659,7 +660,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
aTab._endRemoveArgs = [closeWindow, newTab];
// swapBrowsersAndCloseOther will take care of closing the window without animation.
@@ -5856,13 +6028,7 @@
@@ -5856,13 +6029,7 @@
aTab._mouseleave();
if (newTab) {
@@ -674,7 +675,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
} else {
TabBarVisibility.update();
}
@@ -5995,6 +6161,7 @@
@@ -5995,6 +6162,7 @@
this.tabs[i]._tPos = i;
}
@@ -682,7 +683,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
if (!this._windowIsClosing) {
// update tab close buttons state
this.tabContainer._updateCloseButtons();
@@ -6225,6 +6392,7 @@
@@ -6225,6 +6393,7 @@
}
let excludeTabs = new Set(aExcludeTabs);
@@ -690,7 +691,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
// If this tab has a successor, it should be selectable, since
// hiding or closing a tab removes that tab as a successor.
@@ -6237,15 +6405,22 @@
@@ -6237,15 +6406,22 @@
!excludeTabs.has(aTab.owner) &&
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")
) {
@@ -715,7 +716,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
let tab = this.tabContainer.findNextTab(aTab, {
direction: 1,
filter: _tab => remainingTabs.includes(_tab),
@@ -6259,7 +6434,7 @@
@@ -6259,7 +6435,7 @@
}
if (tab) {
@@ -724,7 +725,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
}
// If no qualifying visible tab was found, see if there is a tab in
@@ -6280,7 +6455,7 @@
@@ -6280,7 +6456,7 @@
});
}
@@ -733,7 +734,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
}
_blurTab(aTab) {
@@ -6291,7 +6466,7 @@
@@ -6291,7 +6467,7 @@
* @returns {boolean}
* False if swapping isn't permitted, true otherwise.
*/
@@ -742,7 +743,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
// Do not allow transfering a private tab to a non-private window
// and vice versa.
if (
@@ -6345,6 +6520,7 @@
@@ -6345,6 +6521,7 @@
// fire the beforeunload event in the process. Close the other
// window if this was its last tab.
if (
@@ -750,7 +751,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
!remoteBrowser._beginRemoveTab(aOtherTab, {
adoptedByTab: aOurTab,
closeWindowWithLastTab: true,
@@ -6356,7 +6532,7 @@
@@ -6356,7 +6533,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.
@@ -759,7 +760,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
if (closeWindow) {
let win = aOtherTab.ownerGlobal;
win.windowUtils.suppressAnimation(true);
@@ -6484,11 +6660,13 @@
@@ -6484,11 +6661,13 @@
}
// Finish tearing down the tab that's going away.
@@ -773,7 +774,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
this.setTabTitle(aOurTab);
@@ -6690,10 +6868,10 @@
@@ -6690,10 +6869,10 @@
SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
}
@@ -786,7 +787,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
aTab.selected ||
aTab.closing ||
// Tabs that are sharing the screen, microphone or camera cannot be hidden.
@@ -6753,7 +6931,8 @@
@@ -6753,7 +6932,8 @@
* @param {object} [aOptions={}]
* Key-value pairs that will be serialized into the features string.
*/
@@ -796,7 +797,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
if (this.tabs.length == 1) {
return null;
}
@@ -6770,7 +6949,7 @@
@@ -6770,7 +6950,7 @@
// tell a new window to take the "dropped" tab
let args = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
args.appendElement(aTab.splitview ?? aTab);
@@ -805,7 +806,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
private: PrivateBrowsingUtils.isWindowPrivate(window),
features: Object.entries(aOptions)
.map(([key, value]) => `${key}=${value}`)
@@ -6778,6 +6957,8 @@
@@ -6778,6 +6958,8 @@
openerWindow: window,
args,
});
@@ -814,7 +815,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
}
/**
@@ -6890,7 +7071,7 @@
@@ -6890,7 +7072,7 @@
* `true` if element is a `<tab-group>`
*/
isTabGroup(element) {
@@ -823,7 +824,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
}
/**
@@ -6975,8 +7156,8 @@
@@ -6975,8 +7157,8 @@
}
// Don't allow mixing pinned and unpinned tabs.
@@ -834,7 +835,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
} else {
tabIndex = Math.max(tabIndex, this.pinnedTabCount);
}
@@ -7005,13 +7186,19 @@
@@ -7005,13 +7187,19 @@
this.#handleTabMove(
element,
() => {
@@ -856,7 +857,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
let useAfter = false;
if (this.isTab(element)) {
useAfter = neighbor && tabIndex > element._tPos;
@@ -7076,23 +7263,31 @@
@@ -7076,23 +7264,31 @@
#moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) {
if (this.isTabGroupLabel(targetElement)) {
targetElement = targetElement.group;
@@ -894,7 +895,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
} 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
@@ -7105,12 +7300,35 @@
@@ -7105,12 +7301,35 @@
// 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.
@@ -931,7 +932,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
// We want to include the splitview wrapper if it's the targetElement, but
// not in the case where we want to reverse tabs within the same splitview.
@@ -7119,6 +7337,7 @@
@@ -7119,6 +7338,7 @@
}
let getContainer = () =>
@@ -939,7 +940,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
element.pinned
? this.tabContainer.pinnedTabsContainer
: this.tabContainer;
@@ -7127,11 +7346,15 @@
@@ -7127,11 +7347,15 @@
element,
() => {
if (moveBefore) {
@@ -956,7 +957,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
}
},
metricsContext
@@ -7205,10 +7428,10 @@
@@ -7205,10 +7429,10 @@
* @param {TabMetricsContext} [metricsContext]
*/
moveTabToExistingGroup(aTab, aGroup, metricsContext) {
@@ -969,7 +970,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
return;
}
if (aTab.group && aTab.group.id === aGroup.id) {
@@ -7281,6 +7504,7 @@
@@ -7281,6 +7505,7 @@
let state = {
tabIndex: tab._tPos,
@@ -977,7 +978,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
};
if (tab.visible) {
state.elementIndex = tab.elementIndex;
@@ -7312,7 +7536,7 @@
@@ -7312,7 +7537,7 @@
let changedSplitView =
previousTabState.splitViewId != currentTabState.splitViewId;
@@ -986,7 +987,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
tab.dispatchEvent(
new CustomEvent("TabMove", {
bubbles: true,
@@ -7354,6 +7578,10 @@
@@ -7354,6 +7579,10 @@
moveActionCallback();
@@ -997,7 +998,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
// Clear tabs cache after moving nodes because the order of tabs may have
// changed.
this.tabContainer._invalidateCachedTabs();
@@ -7404,7 +7632,22 @@
@@ -7404,7 +7633,22 @@
* @returns {object}
* The new tab in the current window, null if the tab couldn't be adopted.
*/
@@ -1021,7 +1022,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
// Swap the dropped tab with a new one we create and then close
// it in the other window (making it seem to have moved between
// windows). We also ensure that the tab we create to swap into has
@@ -7447,6 +7690,8 @@
@@ -7447,6 +7691,8 @@
}
params.skipLoad = true;
let newTab = this.addWebTab("about:blank", params);
@@ -1030,7 +1031,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
aTab.container.tabDragAndDrop.finishAnimateTabMove();
@@ -8149,7 +8394,7 @@
@@ -8149,7 +8395,7 @@
// preventDefault(). It will still raise the window if appropriate.
return;
}
@@ -1039,7 +1040,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
window.focus();
aEvent.preventDefault();
}
@@ -8166,7 +8411,6 @@
@@ -8166,7 +8412,6 @@
on_TabGroupCollapse(aEvent) {
aEvent.target.tabs.forEach(tab => {
@@ -1047,7 +1048,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
});
}
@@ -8500,7 +8744,9 @@
@@ -8500,7 +8745,9 @@
let filter = this._tabFilters.get(tab);
if (filter) {
@@ -1057,7 +1058,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
let listener = this._tabListeners.get(tab);
if (listener) {
@@ -9306,6 +9552,7 @@
@@ -9306,6 +9553,7 @@
aWebProgress.isTopLevel
) {
this.mTab.setAttribute("busy", "true");
@@ -1065,7 +1066,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
gBrowser._tabAttrModified(this.mTab, ["busy"]);
this.mTab._notselectedsinceload = !this.mTab.selected;
}
@@ -9386,6 +9633,7 @@
@@ -9386,6 +9634,7 @@
// known defaults. Note we use the original URL since about:newtab
// redirects to a prerendered page.
const shouldRemoveFavicon =
@@ -1073,7 +1074,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
!this.mBrowser.mIconURL &&
!ignoreBlank &&
!(originalLocation.spec in FAVICON_DEFAULTS);
@@ -9560,13 +9808,6 @@
@@ -9560,13 +9809,6 @@
this.mBrowser.originalURI = aRequest.originalURI;
}
@@ -1087,7 +1088,7 @@ index 2643e1a2aa14ba5cb4a64a92e1c2dfa5f07d242f..642b74cdf0edc63e5cf4ca8c69481e25
}
let userContextId = this.mBrowser.getAttribute("usercontextid") || 0;
@@ -10450,7 +10691,7 @@ var TabContextMenu = {
@@ -10450,7 +10692,7 @@ var TabContextMenu = {
);
contextUnpinSelectedTabs.hidden =
!this.contextTab.pinned || !this.multiselected;

View File

@@ -1,5 +1,5 @@
diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css
index 203b546933842f4b0134188fda020c4db4dcd0d2..011bcfb023d0cabd55dfa7e49d3409383217e2ca 100644
index 203b546933842f4b0134188fda020c4db4dcd0d2..0d67deabac2984574636248a16e58d1669f2e1a4 100644
--- a/browser/themes/shared/tabbrowser/tabs.css
+++ b/browser/themes/shared/tabbrowser/tabs.css
@@ -24,7 +24,7 @@
@@ -97,7 +97,15 @@ index 203b546933842f4b0134188fda020c4db4dcd0d2..011bcfb023d0cabd55dfa7e49d340938
&:is([soundplaying], [muted], [activemedia-blocked]) {
display: flex;
}
@@ -1614,7 +1606,7 @@ tab-group {
@@ -1048,7 +1040,6 @@ tab-split-view-wrapper[dragtarget] {
.tabbrowser-tab:is([image], [pinned]) > .tab-stack > .tab-content[attention]:not([selected]),
.tabbrowser-tab > .tab-stack > .tab-content[pinned][titlechanged]:not([selected]),
#tabbrowser-tabs[orient="vertical"] .tabbrowser-tab > .tab-stack > .tab-content[titlechanged]:not([selected]) {
- background-image: radial-gradient(circle, var(--tab-attention-dot-color), var(--tab-attention-dot-color) 2px, transparent 2px);
background-position: center bottom 6.5px;
background-size: 4px 4px;
background-repeat: no-repeat;
@@ -1614,7 +1605,7 @@ tab-group {
}
#tabbrowser-tabs[orient="vertical"][expanded] {
@@ -106,7 +114,7 @@ index 203b546933842f4b0134188fda020c4db4dcd0d2..011bcfb023d0cabd55dfa7e49d340938
&[movingtab][movingtab-addToGroup]:not([movingtab-group], [movingtab-ungroup]) tab-group > .tabbrowser-tab:is(:active, [multiselected]) {
margin-inline-start: var(--space-medium);
}
@@ -2089,7 +2081,7 @@ tab-group {
@@ -2089,7 +2080,7 @@ tab-group {
}
}
@@ -115,7 +123,7 @@ index 203b546933842f4b0134188fda020c4db4dcd0d2..011bcfb023d0cabd55dfa7e49d340938
#vertical-tabs-newtab-button {
appearance: none;
min-height: var(--tab-min-height);
@@ -2100,7 +2092,7 @@ tab-group {
@@ -2100,7 +2091,7 @@ tab-group {
margin-inline: var(--tab-inner-inline-margin);
#tabbrowser-tabs[orient="vertical"]:not([expanded]) & > .toolbarbutton-text {
@@ -124,7 +132,7 @@ index 203b546933842f4b0134188fda020c4db4dcd0d2..011bcfb023d0cabd55dfa7e49d340938
}
&:hover {
@@ -2124,7 +2116,7 @@ tab-group {
@@ -2124,7 +2115,7 @@ tab-group {
* flex container. #tabs-newtab-button is a child of the arrowscrollbox where
* we don't want a gap (between tabs), so we have to add some margin.
*/
@@ -133,7 +141,7 @@ index 203b546933842f4b0134188fda020c4db4dcd0d2..011bcfb023d0cabd55dfa7e49d340938
margin-block: var(--tab-block-margin);
}
@@ -2312,7 +2304,6 @@ tab-group {
@@ -2312,7 +2303,6 @@ tab-group {
&:not([expanded]) {
.tabbrowser-tab[pinned] {
@@ -141,7 +149,7 @@ index 203b546933842f4b0134188fda020c4db4dcd0d2..011bcfb023d0cabd55dfa7e49d340938
}
.tab-background {
@@ -2352,8 +2343,8 @@ tab-group {
@@ -2352,8 +2342,8 @@ tab-group {
display: block;
position: absolute;
inset: auto;
@@ -152,7 +160,7 @@ index 203b546933842f4b0134188fda020c4db4dcd0d2..011bcfb023d0cabd55dfa7e49d340938
&:-moz-window-inactive {
background-image:
@@ -2438,9 +2429,6 @@ tab-group {
@@ -2438,9 +2428,6 @@ tab-group {
:root:not([privatebrowsingmode]) :is(toolbarbutton, toolbarpaletteitem) ~ #tabbrowser-tabs,
:root[privatebrowsingmode] :is(toolbarbutton:not(#firefox-view-button), toolbarpaletteitem:not(#wrapper-firefox-view-button)) ~ #tabbrowser-tabs {
@@ -162,7 +170,7 @@ index 203b546933842f4b0134188fda020c4db4dcd0d2..011bcfb023d0cabd55dfa7e49d340938
}
:root[privatebrowsingmode] :is(#firefox-view-button, #menu_openFirefoxView) {
@@ -2472,7 +2460,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button {
@@ -2472,7 +2459,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button {
list-style-image: url(chrome://global/skin/icons/plus.svg);
}

View File

@@ -101,10 +101,12 @@ window.gZenUIManager = {
) {
const yValues = rawKeyframes.y || [];
const xValues = rawKeyframes.x || [];
const scaleValues = rawKeyframes.scale || [];
const scaleYValues = rawKeyframes.scaleY || [];
const scaleXValues = rawKeyframes.scaleX || [];
delete rawKeyframes.y;
delete rawKeyframes.x;
delete rawKeyframes.scale;
delete rawKeyframes.scaleY;
delete rawKeyframes.scaleX;
rawKeyframes.transform = [];
if (
yValues.length !== 0 &&
@@ -116,14 +118,17 @@ window.gZenUIManager = {
const keyframeLength = Math.max(
yValues.length,
xValues.length,
scaleValues.length
scaleYValues.length,
scaleXValues.length
);
for (let i = 0; i < keyframeLength; i++) {
const y = yValues[i] !== undefined ? `translateY(${yValues[i]}px)` : "";
const x = xValues[i] !== undefined ? `translateX(${xValues[i]}px)` : "";
const scale =
scaleValues[i] !== undefined ? `scale(${scaleValues[i]})` : "";
rawKeyframes.transform.push(`${x} ${y} ${scale}`.trim());
const scaleY =
scaleYValues[i] !== undefined ? `scaleY(${scaleYValues[i]})` : "";
const scaleX =
scaleXValues[i] !== undefined ? `scaleX(${scaleXValues[i]})` : "";
rawKeyframes.transform.push(`${x} ${y} ${scaleX} ${scaleY}`.trim());
}
}
let keyframes = [];

View File

@@ -58,18 +58,15 @@
}
@keyframes zen-progress-bar-pulse {
0% {
transform: scale(0.8) translate(-50%, -50%);
from {
transform: scale(0.85) translate(-50%, -50%);
opacity: 0.6;
}
50% {
to {
transform: scale(0.95) translate(-50%, -50%);
opacity: 1;
}
100% {
transform: scale(0.8) translate(-50%, -50%);
opacity: 0.6;
}
}
@keyframes zen-progress-bar-long-load {

View File

@@ -695,6 +695,7 @@
:root:is([zen-no-padding="true"], [inDOMFullscreen="true"]) & {
top: 4px;
}
left: 50%;
transform: translate(-50%, -50%) scale(0);
background: var(--zen-loading-progress-bar-color);
@@ -707,8 +708,10 @@
transform .3s ease-in-out;
overflow: clip;
pointer-events: none;
animation: zen-progress-bar-pulse 1.5s linear infinite forwards;
animation: zen-progress-bar-pulse 1s ease-in-out infinite forwards;
animation-direction: alternate;
transform-origin: 0 0;
contain: content;
&[long-load="true"] {
opacity: 1;

View File

@@ -50,7 +50,7 @@ export class ZenProgressBar extends ZenUIComponent {
this.window.gZenUIManager.elementAnimate(
this.#element,
{
opacity: [0, 0.6],
opacity: [0, 0.8],
},
{
duration: 400,

View File

@@ -119,6 +119,10 @@
init() {
super.init();
this.handle_windowDragEnter = this.handle_windowDragEnter.bind(this);
gZenWorkspaces.workspaceIcons.addEventListener(
"dragover",
this.handle_spaceIconDragOver.bind(this)
);
window.addEventListener(
"dragleave",
this.handle_windowDragLeave.bind(this),
@@ -676,6 +680,31 @@
}
}
#onSpaceChanged(spaceChanged, dt) {
if (AppConstants.platform !== "macosx") {
// See the hack in #createDragImageForTabs for more details which
// explains why we need to do this on non-macOS platforms.
return;
}
let tabs = this.originalDragImageArgs[0].children;
const { isDarkMode, isExplicitMode } =
gZenThemePicker.getGradientForWorkspace(spaceChanged, {
getGradient: false,
});
for (let tab of tabs) {
if (isExplicitMode) {
tab.style.colorScheme = isDarkMode ? "dark" : "light";
} else {
tab.style.colorScheme = "";
}
}
requestAnimationFrame(() => {
requestAnimationFrame(() => {
dt.updateDragImage(...this.originalDragImageArgs);
});
});
}
#handle_sidebarDragOver(event) {
const dt = event.dataTransfer;
const draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
@@ -696,28 +725,7 @@
/* Disable wrapping */ true
)
.then(spaceChanged => {
if (AppConstants.platform !== "macosx") {
// See the hack in #createDragImageForTabs for more details which
// explains why we need to do this on non-macOS platforms.
return;
}
let tabs = this.originalDragImageArgs[0].children;
const { isDarkMode, isExplicitMode } =
gZenThemePicker.getGradientForWorkspace(spaceChanged, {
getGradient: false,
});
for (let tab of tabs) {
if (isExplicitMode) {
tab.style.colorScheme = isDarkMode ? "dark" : "light";
} else {
tab.style.colorScheme = "";
}
}
requestAnimationFrame(() => {
requestAnimationFrame(() => {
dt.updateDragImage(...this.originalDragImageArgs);
});
});
this.#onSpaceChanged(spaceChanged, dt);
});
this.#changeSpaceTimer = null;
}, this._dndSwitchSpaceDelay);
@@ -727,6 +735,27 @@
}
}
handle_spaceIconDragOver(event) {
const dt = event.dataTransfer;
const draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
if (draggedTab.hasAttribute("zen-essential")) {
return;
}
const target = event.target;
const spaceId = target.getAttribute("zen-workspace-id");
if (!spaceId) {
return;
}
this.clearDragOverVisuals();
const currentSpaceId = gZenWorkspaces.activeWorkspace;
if (spaceId === currentSpaceId || gZenWorkspaces._animatingChange) {
return;
}
gZenWorkspaces.changeWorkspaceWithID(spaceId).then(spaceChanged => {
this.#onSpaceChanged(spaceChanged, dt);
});
}
#handle_tabDragOverToSplit(event) {
if (!this._dndSplitEnabled) {
return;
@@ -1238,18 +1267,24 @@
) {
let lastTab = gBrowser.tabs.at(-1);
let pinnedTabsCount = gBrowser._numVisiblePinTabsWithoutCollapsed;
let isHoveringSeparator =
event.target.parentElement.classList.contains(
"zen-workspace-pinned-tabs-section"
);
// Only if there are no normal tabs to drop after
showIndicatorUnderNewTabButton =
lastTab.hasAttribute("zen-empty-tab");
let useLastPinnd =
(hoveringPeriphery ||
(showIndicatorUnderNewTabButton &&
!(pinnedTabsCount - gBrowser._numZenEssentials))) &&
Services.prefs.getBoolPref("zen.view.show-newtab-button-top");
let useLastPinned =
(showIndicatorUnderNewTabButton &&
!(pinnedTabsCount - gBrowser._numZenEssentials) &&
Services.prefs.getBoolPref("zen.view.show-newtab-button-top")) ||
isHoveringSeparator;
dropElement =
(useLastPinnd
? this._tabbrowserTabs.ariaFocusableItems.at(pinnedTabsCount)
(useLastPinned
? this._tabbrowserTabs.ariaFocusableItems.at(
pinnedTabsCount ? pinnedTabsCount - 1 : 0
)
: this._tabbrowserTabs.ariaFocusableItems.at(-1)) || lastTab;
}
}

View File

@@ -744,8 +744,14 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
const onKeyDown = event => {
// Arrow down and up to navigate through the list
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
if (
event.key === "ArrowDown" ||
event.key === "ArrowUp" ||
event.key === "Tab"
) {
event.preventDefault();
let isUp =
event.key === "ArrowUp" || (event.key === "Tab" && event.shiftKey);
const items = Array.from(tabsList.children).filter(
item => !item.hidden
);
@@ -755,9 +761,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
let index = items.indexOf(
tabsList.querySelector(".folders-tabs-list-item[selected]")
);
if (event.key === "ArrowDown") {
if (!isUp) {
index = (index + 1) % items.length;
} else if (event.key === "ArrowUp") {
} else {
index = (index - 1 + items.length) % items.length;
}
items.forEach(item => item.removeAttribute("selected"));

View File

@@ -39,8 +39,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
ARC_HEIGHT_RATIO: 0.2, // Arc height = distance * ratio (capped at MAX_ARC_HEIGHT)
});
#GLANCE_ANIMATION_DURATION =
Services.prefs.getIntPref("zen.glance.animation-duration") / 1000;
#GLANCE_ANIMATION_DURATION = Services.prefs.getIntPref(
"zen.glance.animation-duration"
);
init() {
this.#setupEventListeners();
@@ -294,7 +295,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
{
duration: 0.2,
type: "spring",
delay: this.#GLANCE_ANIMATION_DURATION - 0.2,
delay: this.#GLANCE_ANIMATION_DURATION / 1000 - 0.2,
bounce: 0,
}
);
@@ -450,7 +451,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
opacity: [1, 0.3],
},
{
duration: this.#GLANCE_ANIMATION_DURATION,
duration: this.#GLANCE_ANIMATION_DURATION / 1000,
type: "spring",
bounce: 0.2,
}
@@ -536,13 +537,13 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
// nice fade-in effect to the content. But if it doesn't exist,
// we just fall back to always showing the browser directly.
if (data.elementData) {
gZenUIManager.motion
.animate(
gZenUIManager
.elementAnimate(
this.contentWrapper,
{ opacity: [0, 1] },
{
duration: this.#GLANCE_ANIMATION_DURATION / 4,
easing: "easeInOut",
easing: "ease-in-out",
}
)
.then(() => {
@@ -559,12 +560,12 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
browserElement.zenModeActive = false;
browserElement.docShellIsActive = false;
}
gZenUIManager.motion
.animate(this.browserWrapper, arcSequence, {
gZenUIManager
.elementAnimate(this.browserWrapper, arcSequence, {
duration: gZenUIManager.testingEnabled
? 0
: this.#GLANCE_ANIMATION_DURATION,
ease: "easeInOut",
easing: "ease-in-out",
})
.then(() => {
if (shouldDeactivateDocShell) {
@@ -971,7 +972,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
{
duration: 0.2,
type: "spring",
bounce: this.#GLANCE_ANIMATION_DURATION - 0.1,
bounce: this.#GLANCE_ANIMATION_DURATION / 1000 - 0.1,
}
)
.then(() => {
@@ -1019,7 +1020,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
opacity: [0.3, 1],
},
{
duration: this.#GLANCE_ANIMATION_DURATION / 1.5,
duration: this.#GLANCE_ANIMATION_DURATION / 1000 / 1.5,
type: "spring",
bounce: 0,
}
@@ -1062,10 +1063,10 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
this.browserWrapper.style.width = "";
this.browserWrapper.style.height = "";
gZenUIManager.motion
.animate(this.browserWrapper, arcSequence, {
gZenUIManager
.elementAnimate(this.browserWrapper, arcSequence, {
duration: this.#GLANCE_ANIMATION_DURATION,
ease: "easeOut",
easing: "ease-out",
})
.then(() => {
// Remove element preview after closing animation
@@ -1573,9 +1574,6 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
this.#handleZenFolderPinning();
gBrowser.moveTabAfter(this.#currentTab, this.#currentParentTab);
const browserRect = window.windowUtils.getBoundsWithoutFlushing(
this.browserWrapper
);
this.#prepareTabForFullOpen();
const sidebarButtons = this.browserWrapper.querySelector(
@@ -1596,7 +1594,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
return;
}
await this.#animateFullOpen(browserRect);
await this.#animateFullOpen();
this.finishOpeningGlance();
}
@@ -1632,31 +1630,27 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
/**
* Animate the full opening process
*
* @param {object} browserRect - The browser rectangle
*/
async #animateFullOpen(browserRect) {
async #animateFullOpen() {
// Write styles early to avoid flickering
this.browserWrapper.style.opacity = 1;
this.browserWrapper.style.width = `${browserRect.width}px`;
this.browserWrapper.style.height = `${browserRect.height}px`;
this.browserWrapper.style.width = "100%";
this.browserWrapper.style.height = "100%";
await gZenUIManager.motion.animate(
this.browserWrapper,
await gZenUIManager.elementAnimate(
this.browserWrapper.parentElement,
{
width: ["80%", "100%"],
height: ["100%", "100%"],
scale: [1, 1.005, 1],
},
{
duration: this.#GLANCE_ANIMATION_DURATION,
type: "spring",
bounce: 0,
duration: 250,
easing: "ease-in-out",
}
);
this.browserWrapper.style.scale = "";
this.browserWrapper.style.opacity = "";
this.browserWrapper.style.width = "";
this.browserWrapper.style.height = "";
this.browserWrapper.style.opacity = "";
gZenViewSplitter.deactivateCurrentSplitView({ removeDeckSelected: true });
}

View File

@@ -9,6 +9,9 @@
display: flex;
z-index: 999;
will-change: transform, opacity;
contain: content;
top: 15px;
padding: 12px;
gap: 12px;
@@ -121,6 +124,7 @@
&:not([has-finished-animation="true"]) {
will-change: transform;
contain: layout size;
transform-origin: 0 0;
#statuspanel {

View File

@@ -1602,7 +1602,6 @@ class nsZenWorkspaces {
}
#prepareNewWorkspace(space) {
document.documentElement.setAttribute("zen-workspace-id", space.uuid);
let tabCount = 0;
for (let tab of gBrowser.tabs) {
const isEssential = tab.getAttribute("zen-essential") === "true";
@@ -1643,12 +1642,12 @@ class nsZenWorkspaces {
async changeWorkspaceWithID(workspaceID, ...args) {
const workspace = this.getWorkspaceFromId(workspaceID);
await this.changeWorkspace(workspace, ...args);
return await this.changeWorkspace(workspace, ...args);
}
async changeWorkspace(workspace, ...args) {
if (!this.workspaceEnabled) {
return;
return workspace;
}
this.#currentSpaceSwitchContext.animations.forEach(animation => {
animation.complete();
@@ -1668,6 +1667,7 @@ class nsZenWorkspaces {
}
this.#inChangingWorkspace = false;
resolve();
return workspace;
}
_cancelSwipeAnimation() {
@@ -2429,9 +2429,6 @@ class nsZenWorkspaces {
tabToSelect,
{ previousWorkspaceIndex, previousWorkspace } = {}
) {
// Update document state
document.documentElement.setAttribute("zen-workspace-id", workspace.uuid);
// Recalculate new tab observers
gBrowser.tabContainer.observe(
null,
@@ -2975,8 +2972,7 @@ class nsZenWorkspaces {
}
let nextWorkspace = workspaces[targetIndex];
await this.changeWorkspace(nextWorkspace, { whileScrolling });
return nextWorkspace;
return await this.changeWorkspace(nextWorkspace, { whileScrolling });
}
#initializeWorkspaceTabContextMenus() {
@@ -3000,9 +2996,8 @@ class nsZenWorkspaces {
? gBrowser.selectedTabs
: [TabContextMenu.contextTab];
document.getElementById("tabContextMenu").hidePopup();
const previousWorkspaceID =
document.documentElement.getAttribute("zen-workspace-id");
for (let tab of tabs) {
const previousWorkspaceID = tab.getAttribute("zen-workspace-id");
this.moveTabToWorkspace(tab, workspaceID);
if (this.lastSelectedWorkspaceTabs[previousWorkspaceID] === tab) {
// This tab is no longer the last selected tab in the previous workspace because it's being moved to

View File

@@ -1239,13 +1239,24 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
/**
* Splits the selected tabs.
*
* @param {Tab|null} otherTabHint - An optional hint for another tab to split with (used for glance tabs).
*/
contextSplitTabs() {
contextSplitTabs(otherTabHint = null) {
let tabs;
if (TabContextMenu.contextTab.multiselected) {
let currentTab = TabContextMenu.contextTab || gBrowser.selectedTab;
if (currentTab.multiselected) {
tabs = gBrowser.selectedTabs;
} else {
tabs = [TabContextMenu.contextTab];
tabs = [currentTab];
}
if (otherTabHint && !tabs.includes(otherTabHint)) {
tabs.push(otherTabHint);
}
if (tabs.length < 2) {
gBrowser.selectedTab = tabs[0];
this.createEmptySplit();
return;
}
// If all are already in a split view, we unsplit them first.
if (tabs.every(tab => tab.splitView)) {
@@ -1265,10 +1276,7 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
* @returns {boolean} True if the tabs can be split, false otherwise.
*/
contextCanSplitTabs() {
if (
window.gBrowser.selectedTabs.length < 2 ||
window.gBrowser.selectedTabs.length > this.MAX_TABS
) {
if (window.gBrowser.selectedTabs.length > this.MAX_TABS) {
return false;
}
for (const tab of window.gBrowser.selectedTabs) {
@@ -1323,7 +1331,7 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
* @param {Array} tabs
* @param {Tab} relativeTab
*/
_moveTabsToContainer(tabs, relativeTab) {
#moveTabsToContainer(tabs, relativeTab) {
const relativeTabIsPinned = relativeTab.pinned;
const relativeTabIsEssential = relativeTab.hasAttribute("zen-essential");
@@ -1340,6 +1348,32 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
}
}
#useTabsToSplit(tabs) {
// If there's ANY pinned tab on the list, we clone the pinned tab
// state to all the tabs
const allArePinned = tabs.every(tab => tab.pinned);
const thereIsOnePinned = tabs.some(tab => tab.pinned);
const thereIsOneEssential = tabs.some(tab =>
tab.hasAttribute("zen-essential")
);
const thereIsOneLiveFolder = tabs.some(tab =>
tab.hasAttribute("zen-live-folder-item-id")
);
if (
thereIsOneEssential ||
(thereIsOnePinned && !allArePinned) ||
thereIsOneLiveFolder
) {
for (let i = 0; i < tabs.length; i++) {
const tab = tabs[i];
if (tab.pinned) {
tabs[i] = gBrowser.duplicateTab(tab, true);
}
}
}
}
/**
* Splits the given tabs.
*
@@ -1364,17 +1398,20 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
let shouldActivateSplit =
(initialIndex >= 0 || tabs.includes(window.gBrowser.selectedTab)) &&
!this._sessionRestoring;
if (existingSplitTab) {
this._moveTabsToContainer(tabs, tabs[tabIndexToUse]);
const groupIndex = this._data.findIndex(group =>
group.tabs.includes(existingSplitTab)
);
const group = this._data[groupIndex];
const gridTypeChange = gridType && group.gridType !== gridType;
const newTabsAdded = tabs.find(t => !group.tabs.includes(t));
if (group.tabs.length >= this.MAX_TABS) {
gZenUIManager.showToast("zen-split-view-limit-toast");
return;
}
this.#useTabsToSplit(tabs);
this.#moveTabsToContainer(tabs, tabs[tabIndexToUse]);
const gridTypeChange = gridType && group.gridType !== gridType;
const newTabsAdded = tabs.find(t => !group.tabs.includes(t));
if (gridTypeChange && !newTabsAdded) {
// reset layout
group.gridType = gridType;
@@ -1406,30 +1443,7 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
return group;
}
// We are here if none of the tabs have been previously split
// If there's ANY pinned tab on the list, we clone the pinned tab
// state to all the tabs
const allArePinned = tabs.every(tab => tab.pinned);
const thereIsOnePinned = tabs.some(tab => tab.pinned);
const thereIsOneEssential = tabs.some(tab =>
tab.hasAttribute("zen-essential")
);
const thereIsOneLiveFolder = tabs.some(tab =>
tab.hasAttribute("zen-live-folder-item-id")
);
if (
thereIsOneEssential ||
(thereIsOnePinned && !allArePinned) ||
thereIsOneLiveFolder
) {
for (let i = 0; i < tabs.length; i++) {
const tab = tabs[i];
if (tab.pinned) {
tabs[i] = gBrowser.duplicateTab(tab, true);
}
}
}
this.#useTabsToSplit(tabs);
gridType ??= "grid";
@@ -2172,7 +2186,7 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
splitGroup &&
(!draggedTab.group || draggedTab.group !== splitGroup)
) {
this._moveTabsToContainer([draggedTab], droppedOnTab);
this.#moveTabsToContainer([draggedTab], droppedOnTab);
gBrowser.moveTabToExistingGroup(draggedTab, splitGroup);
if (hoverSide === "left" || hoverSide === "top") {
try {

View File

@@ -857,7 +857,9 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
const pinUrl = tab._zenPinnedInitialState.entry.url.split("#")[0];
const currentUrl = location.split("#")[0];
// Add an indicator that the pin has been changed
if (Services.io.newURI(currentUrl).spec === Services.io.newURI(pinUrl).spec) {
if (
Services.io.newURI(currentUrl).spec === Services.io.newURI(pinUrl).spec
) {
this.resetPinChangedUrl(tab);
return;
}

View File

@@ -474,13 +474,13 @@
overflow-y: auto;
height: 100%;
:root[zen-workspace-id][zen-sidebar-expanded="true"] & {
:root[zen-sidebar-expanded="true"] & {
margin-left: calc(-1 * var(--zen-toolbox-padding));
width: calc(100% + var(--zen-toolbox-padding) * 2);
}
}
:root[zen-workspace-id] #pinned-tabs-container {
#pinned-tabs-container {
display: none;
}

View File

@@ -12,10 +12,6 @@ add_task(async function test_Issue_10455() {
let newWindow = await BrowserTestUtils.openNewBrowserWindow();
await newWindow.gZenWorkspaces.promiseInitialized;
ok(
newWindow.document.documentElement.hasAttribute("zen-workspace-id"),
"New window should have a zen-workspace-id attribute"
);
const unloadEvent = BrowserTestUtils.waitForEvent(newWindow, "unload");
newWindow.BrowserCommands.closeTabOrWindow();
@@ -33,10 +29,6 @@ add_task(async function test_Issue_10455_Dont_Close() {
let newWindow = await BrowserTestUtils.openNewBrowserWindow();
await newWindow.gZenWorkspaces.promiseInitialized;
ok(
newWindow.document.documentElement.hasAttribute("zen-workspace-id"),
"New window should have a zen-workspace-id attribute"
);
newWindow.BrowserCommands.closeTabOrWindow();
Assert.strictEqual(

View File

@@ -12,10 +12,6 @@ add_task(async function test_Private_Mode() {
private: true,
});
await privateWindow.gZenWorkspaces.promiseInitialized;
ok(
privateWindow.document.documentElement.hasAttribute("zen-workspace-id"),
"Private window should have a zen-workspace-id attribute"
);
await BrowserTestUtils.closeWindow(privateWindow);
await SpecialPowers.popPrefEnv();