⚠️ WIP: Working around Signal's wayland issues using nix and nushell
Ive been using Signal Desktop for a bit, however I noticed it never managed to open its window first try, always
needing me to open it twice in a row to work.
Looking into this, I found
this reddit thread
:
Apparently Signal just starts minimized, and we can work around this by overriding this in
~/.config/Signal/ephemeral.json
.
This needs to be done every time we start Signal, since it tends to overwrite this file.
Perfect opportunity to learn a little more nix!
Chapter 1: Patch signal-desktop
I found an issue showing a patch that seems to fix it - can we just copy/paste this?
After stumbling over this issue, it would have been straightforward to try to just take that patch and apply it in my nixpkgs overrides. However, looking at the nixpkgs derivation for Signal, it seems its not built from source, but rather just based on the .deb release - meaning there is no code to patch.
Sadly, not in this case. But even then, nix would recompile the package from source - im sure there is a better approach.
Chapter 2: Override signal-desktop.desktop
Ok, then maybe we can override the .desktop file? Home Manager has a convenient option for it too.
First, we need a script to fix the Signal config - the Reddit post suggests a shell script using jq, but I opted for nushell:
open "/home/lavender/.config/Signal/ephemeral.json" | update window.maximized true | save -f "/home/lavender/.config/Signal/ephemeral.json"
Using pkgs.writers.writeNuBin
, we can get a derivation to use in
xdg.desktopEntries.signal-desktop.exec
.
Great solution! This would work well enough for most uses, unless we try to open Signal directly from a terminal.
Chapter 3: wrapGAppsHook
Like many other packages in nix, signal-desktop uses a wrapper script. You can have a look like this:
which signal-desktop | get path.0 | readlink --canonicalize $in
It sets envvars and options, and we can also use it to run our script before Signal starts.
I found this
gappsWrapArgs
in the derivation, which we should be able to add more options to - however, neither wrapsGAppsHook,
nor makeWrapper mention what option we
need for this,
and makeWrapper does not provide a --help
option or a manual page.
no documentation, really? So its time to stick my snout in source code again?
Luckily, its right here at the top of the file:
# construct an executable file that wraps the actual executable # makeWrapper EXECUTABLE OUT_PATH ARGS # ARGS: # --argv0 NAME : set the name of the executed process to NAME # (if unset or empty, defaults to EXECUTABLE) # --inherit-argv0 : the executable inherits argv0 from the wrapper. # (use instead of --argv0 '$0') # --resolve-argv0 : if argv0 doesn't include a / character, resolve it against PATH # --set VAR VAL : add VAR with value VAL to the executable's environment # --set-default VAR VAL : like --set, but only adds VAR if not already set in # the environment # --unset VAR : remove VAR from the environment # --chdir DIR : change working directory (use instead of --run "cd DIR") # --run COMMAND : run command before the executable # --add-flags ARGS : prepend ARGS to the invocation of the executable # (that is, *before* any arguments passed on the command line) # --append-flags ARGS : append ARGS to the invocation of the executable # (that is, *after* any arguments passed on the command line) # --prefix ENV SEP VAL : suffix/prefix ENV with VAL, separated by SEP # --suffix # --prefix-each ENV SEP VALS : like --prefix, but VALS is a list # --suffix-each ENV SEP VALS : like --suffix, but VALS is a list # --prefix-contents ENV SEP FILES : like --suffix-each, but contents of FILES # are read first and used as VALS # --suffix-contents
With this, we can now put everything together:
nixpkgs.overlays = [ (self: super: { signal-desktop = let fix-signal-config = super.writers.writeNuBin "fix-signal-config" '' let path = "/home/lavender/.config/Signal/ephemeral.json" open $path | update window.maximized true | save -f $path ''; in super.signal-desktop.overrideAttrs (finalAttrs: prevAttrs: { preFixup = prevAttrs.preFixup + '' gappsWrapperArgs+=(--run ${getExe fix-signal-config}) ''; }); }) ]; };
Rebuild your system config, and Signal should now open first try, every time!