Patch Zen window sync blank tabs
This commit is contained in:
parent
8793ecea4d
commit
81a5fef0b3
3 changed files with 278 additions and 33 deletions
54
apps/zen.nix
54
apps/zen.nix
|
|
@ -1,6 +1,19 @@
|
||||||
#./apps/zen.nix
|
#./apps/zen.nix
|
||||||
{ inputs, pkgs, lib, config, ... }:
|
{
|
||||||
let
|
inputs,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
# Zen keeps one live docshell for each logical tab and mirrors about:blank
|
||||||
|
# placeholders into the other synced windows. Upstream 1.23b changes the
|
||||||
|
# placeholder's ownership flags before confirming that the docshell swap
|
||||||
|
# succeeded (zen-browser/desktop#15702), so one failed swap can promote the
|
||||||
|
# blank placeholder and make later selections show "New Tab". Patch the
|
||||||
|
# shipped browser module until Zen includes an upstream fix.
|
||||||
|
windowSyncPatch = ../patches/zen-browser/window-sync-commit-ownership-after-swap.patch;
|
||||||
|
|
||||||
# Autoconfig (mozilla.cfg) runs privileged JS in the parent process at
|
# Autoconfig (mozilla.cfg) runs privileged JS in the parent process at
|
||||||
# startup — the only scriptable way into chrome, since Gecko has no reload
|
# startup — the only scriptable way into chrome, since Gecko has no reload
|
||||||
# for userChrome.css and Zen exposes no command for one.
|
# for userChrome.css and Zen exposes no command for one.
|
||||||
|
|
@ -97,9 +110,8 @@ let
|
||||||
Components.utils.reportError("zen-theme: " + e);
|
Components.utils.reportError("zen-theme: " + e);
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
in
|
in {
|
||||||
{
|
config = lib.mkIf (lib.elem config.networking.hostName ["FredOS-Gaming" "FredOS-Macbook"]) {
|
||||||
config = lib.mkIf (lib.elem config.networking.hostName [ "FredOS-Gaming" "FredOS-Macbook" ]) {
|
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
((inputs.zen-browser.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
|
((inputs.zen-browser.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
|
||||||
# Lands in defaults/pref/autoconfig.js, the only place this pref is
|
# Lands in defaults/pref/autoconfig.js, the only place this pref is
|
||||||
|
|
@ -117,11 +129,41 @@ in
|
||||||
# left behind as a symlink into the unwrapped package. So the app dir
|
# left behind as a symlink into the unwrapped package. So the app dir
|
||||||
# resolved to the unwrapped tree, which has no defaults/pref and no
|
# resolved to the unwrapped tree, which has no defaults/pref and no
|
||||||
# mozilla.cfg, and every pref and script above was silently skipped.
|
# mozilla.cfg, and every pref and script above was silently skipped.
|
||||||
buildCommand = old.buildCommand + ''
|
buildCommand =
|
||||||
|
old.buildCommand
|
||||||
|
+ ''
|
||||||
for exe in "$out"/lib/zen*/zen "$out"/lib/zen*/zen-bin; do
|
for exe in "$out"/lib/zen*/zen "$out"/lib/zen*/zen-bin; do
|
||||||
cp --remove-destination "$(readlink -f "$exe")" "$exe"
|
cp --remove-destination "$(readlink -f "$exe")" "$exe"
|
||||||
chmod u+w "$exe"
|
chmod u+w "$exe"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Zen ships its privileged browser modules inside browser/omni.ja.
|
||||||
|
# Repack that archive with the local Window Sync fix; keeping this as
|
||||||
|
# a normal patch makes an upstream update fail loudly when the source
|
||||||
|
# changes instead of silently dropping the workaround.
|
||||||
|
for omni in "$out"/lib/zen*/browser/omni.ja; do
|
||||||
|
[ -f "$omni" ] || continue
|
||||||
|
cp "$(readlink -f "$omni")" "$omni.local"
|
||||||
|
mv -f "$omni.local" "$omni"
|
||||||
|
|
||||||
|
omniWork="$(mktemp -d)"
|
||||||
|
${pkgs.unzip}/bin/unzip -q "$omni" -d "$omniWork" || {
|
||||||
|
unzipStatus=$?
|
||||||
|
# Mozilla's startup-optimized omnijar places its central
|
||||||
|
# directory first. Info-ZIP extracts it correctly but exits 2
|
||||||
|
# after warning about the nonstandard layout.
|
||||||
|
[ "$unzipStatus" -eq 2 ] || exit "$unzipStatus"
|
||||||
|
}
|
||||||
|
${pkgs.patch}/bin/patch --directory="$omniWork" -p1 \
|
||||||
|
< ${windowSyncPatch}
|
||||||
|
|
||||||
|
rm "$omni"
|
||||||
|
(
|
||||||
|
cd "$omniWork"
|
||||||
|
${pkgs.zip}/bin/zip -0 -X -q -r "$omni" .
|
||||||
|
)
|
||||||
|
rm -rf "$omniWork"
|
||||||
|
done
|
||||||
'';
|
'';
|
||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
|
|
|
||||||
12
flake.lock
generated
12
flake.lock
generated
|
|
@ -299,11 +299,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs_4": {
|
"nixpkgs_4": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1789286504,
|
"lastModified": 1790689126,
|
||||||
"narHash": "sha256-eiEK7cKZORNEvX0GeF3RtNEF/JXhgf2RqSp3230q13E=",
|
"narHash": "sha256-ilerN1WLSvF+HMjziC/Wv99J5y02maDH+6hZPwsORKg=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ef34387ddd751e1ab8857adf4676492d32eb24ec",
|
"rev": "b4fd65b198c599cbe814fcb9f42d25d021595ec9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -526,11 +526,11 @@
|
||||||
"nixpkgs": "nixpkgs_4"
|
"nixpkgs": "nixpkgs_4"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1789702344,
|
"lastModified": 1791022445,
|
||||||
"narHash": "sha256-DfevaOxGu6NKUF+q5hUAg7kFscWQvuC9Yd/CgR4qpgc=",
|
"narHash": "sha256-jr7YVkvOYS+bJjzBwoqtN8b8inJN8UDWziWufAWH1SY=",
|
||||||
"owner": "0xc000022070",
|
"owner": "0xc000022070",
|
||||||
"repo": "zen-browser-flake",
|
"repo": "zen-browser-flake",
|
||||||
"rev": "ef5fe624be04120db77c08c5df6f75a6a4201517",
|
"rev": "e56900732d1fa6f360db502451a457ffe3ca1e6e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,203 @@
|
||||||
|
diff --git a/modules/zen/ZenWindowSync.sys.mjs b/modules/zen/ZenWindowSync.sys.mjs
|
||||||
|
index 8daa5b3..33474a5 100644
|
||||||
|
--- a/modules/zen/ZenWindowSync.sys.mjs
|
||||||
|
+++ b/modules/zen/ZenWindowSync.sys.mjs
|
||||||
|
@@ -781 +781 @@ class nsZenWindowSync {
|
||||||
|
- return;
|
||||||
|
+ return false;
|
||||||
|
@@ -785 +785 @@ class nsZenWindowSync {
|
||||||
|
- return;
|
||||||
|
+ return false;
|
||||||
|
@@ -787 +787 @@ class nsZenWindowSync {
|
||||||
|
- await this.#styleSwapedBrowsers(aOurTab, aOtherTab, () => {
|
||||||
|
+ return this.#styleSwapedBrowsers(aOurTab, aOtherTab, () => {
|
||||||
|
@@ -789 +789 @@ class nsZenWindowSync {
|
||||||
|
- this.#swapBrowserDocShellsInner(aOurTab, aOtherTab);
|
||||||
|
+ return this.#swapBrowserDocShellsInner(aOurTab, aOtherTab);
|
||||||
|
@@ -794,0 +795 @@ class nsZenWindowSync {
|
||||||
|
+ return false;
|
||||||
|
@@ -829,7 +830,8 @@ class nsZenWindowSync {
|
||||||
|
- tabListener = new otherTabBrowser.zenTabProgressListener(
|
||||||
|
- aTab,
|
||||||
|
- otherBrowser,
|
||||||
|
- true,
|
||||||
|
- false
|
||||||
|
- );
|
||||||
|
- otherTabBrowser.zenSetTabProgressListener(aTab, tabListener);
|
||||||
|
+ try {
|
||||||
|
+ tabListener = new otherTabBrowser.zenTabProgressListener(
|
||||||
|
+ aTab,
|
||||||
|
+ otherBrowser,
|
||||||
|
+ true,
|
||||||
|
+ false
|
||||||
|
+ );
|
||||||
|
+ otherTabBrowser.zenSetTabProgressListener(aTab, tabListener);
|
||||||
|
@@ -837,3 +839,6 @@ class nsZenWindowSync {
|
||||||
|
- const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
|
||||||
|
- filter.addProgressListener(tabListener, notifyAll);
|
||||||
|
- otherBrowser.webProgress.addProgressListener(filter, notifyAll);
|
||||||
|
+ const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
|
||||||
|
+ filter.addProgressListener(tabListener, notifyAll);
|
||||||
|
+ otherBrowser.webProgress.addProgressListener(filter, notifyAll);
|
||||||
|
+ } catch (e) {
|
||||||
|
+ console.error(`Error restoring tab progress listener:`, e);
|
||||||
|
+ }
|
||||||
|
@@ -899 +904 @@ class nsZenWindowSync {
|
||||||
|
- return;
|
||||||
|
+ return false;
|
||||||
|
@@ -903,0 +909 @@ class nsZenWindowSync {
|
||||||
|
+ let didSwap = false;
|
||||||
|
@@ -913,0 +920 @@ class nsZenWindowSync {
|
||||||
|
+ didSwap = true;
|
||||||
|
@@ -918,0 +926 @@ class nsZenWindowSync {
|
||||||
|
+ return;
|
||||||
|
@@ -962,0 +971,3 @@ class nsZenWindowSync {
|
||||||
|
+ if (!didSwap) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
@@ -972,9 +983,13 @@ class nsZenWindowSync {
|
||||||
|
- for (let attr of kAttributesToRemove) {
|
||||||
|
- aOtherTab.removeAttribute(attr);
|
||||||
|
- }
|
||||||
|
- if (focus) {
|
||||||
|
- // Recalculate the focus in order to allow the user to continue typing
|
||||||
|
- // inside the web content area without having to click outside and back in.
|
||||||
|
- aOurTab.linkedBrowser.blur();
|
||||||
|
- aOurTab.documentGlobal.gBrowser._adjustFocusAfterTabSwitch(aOurTab);
|
||||||
|
- aOurTab.linkedBrowser.docShellIsActive = true;
|
||||||
|
+ try {
|
||||||
|
+ for (let attr of kAttributesToRemove) {
|
||||||
|
+ aOtherTab.removeAttribute(attr);
|
||||||
|
+ }
|
||||||
|
+ if (focus) {
|
||||||
|
+ // Recalculate the focus in order to allow the user to continue typing
|
||||||
|
+ // inside the web content area without having to click outside and back in.
|
||||||
|
+ aOurTab.linkedBrowser.blur();
|
||||||
|
+ aOurTab.documentGlobal.gBrowser._adjustFocusAfterTabSwitch(aOurTab);
|
||||||
|
+ aOurTab.linkedBrowser.docShellIsActive = true;
|
||||||
|
+ }
|
||||||
|
+ } catch (e) {
|
||||||
|
+ console.error(`Error cleaning up browser after docshell swap:`, e);
|
||||||
|
@@ -981,0 +997 @@ class nsZenWindowSync {
|
||||||
|
+ return true;
|
||||||
|
@@ -997,7 +1013,17 @@ class nsZenWindowSync {
|
||||||
|
- const browserBlob =
|
||||||
|
- await aOtherTab.documentGlobal.PageThumbs.captureToBlob(
|
||||||
|
- aOtherTab.linkedBrowser,
|
||||||
|
- {
|
||||||
|
- fullScale: true,
|
||||||
|
- fullViewport: true,
|
||||||
|
- backgroundColor: "transparent",
|
||||||
|
+ let mySrc = "";
|
||||||
|
+ try {
|
||||||
|
+ const browserBlob =
|
||||||
|
+ await aOtherTab.documentGlobal.PageThumbs.captureToBlob(
|
||||||
|
+ aOtherTab.linkedBrowser,
|
||||||
|
+ {
|
||||||
|
+ fullScale: true,
|
||||||
|
+ fullViewport: true,
|
||||||
|
+ backgroundColor: "transparent",
|
||||||
|
+ }
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ mySrc = await new Promise(r => {
|
||||||
|
+ const reader = new FileReader();
|
||||||
|
+ if (!browserBlob) {
|
||||||
|
+ r("");
|
||||||
|
+ return;
|
||||||
|
@@ -1005,17 +1031,9 @@ class nsZenWindowSync {
|
||||||
|
- );
|
||||||
|
-
|
||||||
|
- let mySrc = await new Promise(r => {
|
||||||
|
- const reader = new FileReader();
|
||||||
|
- if (!browserBlob) {
|
||||||
|
- r("");
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
- reader.readAsDataURL(browserBlob);
|
||||||
|
- reader.onloadend = function () {
|
||||||
|
- // result includes identifier 'data:image/png;base64,' plus the base64 data
|
||||||
|
- r(reader.result);
|
||||||
|
- };
|
||||||
|
- reader.onerror = function () {
|
||||||
|
- r("");
|
||||||
|
- };
|
||||||
|
- });
|
||||||
|
+ reader.readAsDataURL(browserBlob);
|
||||||
|
+ reader.onloadend = function () {
|
||||||
|
+ // result includes identifier 'data:image/png;base64,' plus the base64 data
|
||||||
|
+ r(reader.result);
|
||||||
|
+ };
|
||||||
|
+ reader.onerror = function () {
|
||||||
|
+ r("");
|
||||||
|
+ };
|
||||||
|
+ });
|
||||||
|
@@ -1023,2 +1041,7 @@ class nsZenWindowSync {
|
||||||
|
- await this.#createPseudoImageForBrowser(otherBrowser, mySrc);
|
||||||
|
- callback();
|
||||||
|
+ await this.#createPseudoImageForBrowser(otherBrowser, mySrc);
|
||||||
|
+ } catch (e) {
|
||||||
|
+ // The thumbnail only hides the visual transition. It must not block
|
||||||
|
+ // the docshell transfer or leave the global swap queue pending.
|
||||||
|
+ console.error(`Error preparing docshell swap styling:`, e);
|
||||||
|
+ }
|
||||||
|
+ const didSwap = callback();
|
||||||
|
@@ -1026,5 +1049,10 @@ class nsZenWindowSync {
|
||||||
|
- otherBrowser.setAttribute("zen-pseudo-hidden", "true");
|
||||||
|
- ourBrowser.removeAttribute("zen-pseudo-hidden");
|
||||||
|
- this.#maybeRemovePseudoImageForBrowser(ourBrowser);
|
||||||
|
- ourBrowser.focus();
|
||||||
|
- resolve();
|
||||||
|
+ try {
|
||||||
|
+ otherBrowser.setAttribute("zen-pseudo-hidden", "true");
|
||||||
|
+ ourBrowser.removeAttribute("zen-pseudo-hidden");
|
||||||
|
+ this.#maybeRemovePseudoImageForBrowser(ourBrowser);
|
||||||
|
+ ourBrowser.focus();
|
||||||
|
+ } catch (e) {
|
||||||
|
+ console.error(`Error cleaning up docshell swap styling:`, e);
|
||||||
|
+ } finally {
|
||||||
|
+ resolve(didSwap);
|
||||||
|
+ }
|
||||||
|
@@ -1126 +1153,0 @@ class nsZenWindowSync {
|
||||||
|
- targetTab._zenContentsVisible = true;
|
||||||
|
@@ -1130 +1157 @@ class nsZenWindowSync {
|
||||||
|
- delete tab._zenContentsVisible;
|
||||||
|
+ let didSwap = false;
|
||||||
|
@@ -1132 +1159 @@ class nsZenWindowSync {
|
||||||
|
- this.#swapBrowserDocShellsInner(targetTab, tab, {
|
||||||
|
+ didSwap = this.#swapBrowserDocShellsInner(targetTab, tab, {
|
||||||
|
@@ -1141,0 +1169,5 @@ class nsZenWindowSync {
|
||||||
|
+ if (!didSwap) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ targetTab._zenContentsVisible = true;
|
||||||
|
+ delete tab._zenContentsVisible;
|
||||||
|
@@ -1186,3 +1218,8 @@ class nsZenWindowSync {
|
||||||
|
- otherTabToShow._zenContentsVisible = true;
|
||||||
|
- delete tab._zenContentsVisible;
|
||||||
|
- await this.#swapBrowserDocShellsAsync(otherTabToShow, tab);
|
||||||
|
+ const didSwap = await this.#swapBrowserDocShellsAsync(
|
||||||
|
+ otherTabToShow,
|
||||||
|
+ tab
|
||||||
|
+ );
|
||||||
|
+ if (didSwap) {
|
||||||
|
+ otherTabToShow._zenContentsVisible = true;
|
||||||
|
+ delete tab._zenContentsVisible;
|
||||||
|
+ }
|
||||||
|
@@ -1204 +1240,0 @@ class nsZenWindowSync {
|
||||||
|
- selectedTab._zenContentsVisible = true;
|
||||||
|
@@ -1206 +1241,0 @@ class nsZenWindowSync {
|
||||||
|
- delete otherSelectedTab._zenContentsVisible;
|
||||||
|
@@ -1208 +1243,8 @@ class nsZenWindowSync {
|
||||||
|
- this.#swapBrowserDocShellsAsync(selectedTab, otherSelectedTab)
|
||||||
|
+ this.#swapBrowserDocShellsAsync(selectedTab, otherSelectedTab).then(
|
||||||
|
+ didSwap => {
|
||||||
|
+ if (didSwap) {
|
||||||
|
+ selectedTab._zenContentsVisible = true;
|
||||||
|
+ delete otherSelectedTab._zenContentsVisible;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ )
|
||||||
|
@@ -1209,0 +1252,2 @@ class nsZenWindowSync {
|
||||||
|
+ } else {
|
||||||
|
+ selectedTab._zenContentsVisible = true;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue