#./apps/zen.nix { inputs, pkgs, lib, config, ... }: let # Autoconfig (mozilla.cfg) runs privileged JS in the parent process at # startup — the only scriptable way into chrome, since Gecko has no reload # for userChrome.css and Zen exposes no command for one. # # So don't use userChrome.css at all for the wallpaper theme. Register # /chrome/zen-theme.css as a style-sheet-service USER_SHEET here # and re-register it under a cache-busting URI whenever its mtime moves — # that is what makes a `theme-apply` switch land in a running Zen # (settings/theming.nix writes that file on every switch). A separate file, # not userChrome.css: the legacy loader would hold its own copy of the same # sheet and the two would race on cascade order. themeHotReload = '' try { const { classes: kCc, interfaces: kCi } = Components; const sss = kCc["@mozilla.org/content/style-sheet-service;1"] .getService(kCi.nsIStyleSheetService); const file = Services.dirsvc.get("ProfD", kCi.nsIFile); file.append("chrome"); file.append("zen-theme.css"); const base = Services.io.newFileURI(file).spec; let live = null; const apply = () => { if (!file.exists()) return; // install(1) stamps the copy with the current time, so mtime alone // distinguishes one wallpaper's sheet from the next. const stamp = String(file.lastModifiedTime); if (stamp === live) return; // A fresh query string dodges the CSS loader's per-URI cache; without // it a re-register would hand back the sheet parsed at startup. sss.loadAndRegisterSheet(Services.io.newURI(base + "?" + stamp), sss.USER_SHEET); if (live !== null) { const old = Services.io.newURI(base + "?" + live); if (sss.sheetRegistered(old, sss.USER_SHEET)) sss.unregisterSheet(old, sss.USER_SHEET); } live = stamp; }; const timer = kCc["@mozilla.org/timer;1"].createInstance(kCi.nsITimer); // The observer service holds the only strong reference that keeps the // timer (and this closure) off the GC's list for the session. Services.obs.addObserver({ timer, observe() {} }, "quit-application"); timer.initWithCallback({ notify: apply }, 2000, kCi.nsITimer.TYPE_REPEATING_SLACK); apply(); } catch (e) { Components.utils.reportError(e); } ''; in { config = lib.mkIf (lib.elem config.networking.hostName [ "FredOS-Gaming" "FredOS-Macbook" ]) { environment.systemPackages = [ (inputs.zen-browser.packages.${pkgs.stdenv.hostPlatform.system}.default.override { extraPrefs = themeHotReload; }) ]; }; }