mirror of
https://github.com/nix-community/home-manager.git
synced 2025-12-05 00:21:04 +01:00
By default, dconf uses $XDG_CONFIG_HOME/dconf/user as the user database, but this can be changed by specifying user-db:<name> in a profile file and setting the DCONF_PROFILE environment variable to that profile. One may want to use different user databases for different DE/WMs to avoid collision. Currently the module invokes dconf without touching DCONF_PROFILE, which means that 1) it is unable to configure multiple different user databases, and 2) the behavior of activation script will be affected by the DCONF_PROFILE environment variable when it is invoked, possibly leading to undesired results. This PR adds a dconf.databases option, so that settings under dconf.databases.<name> will be written to $XDG_CONFIG_HOME/dconf/<name>. The old dconf.settings option is left as-is to avoid breaking compatibility.
181 lines
5.8 KiB
Nix
181 lines
5.8 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
let
|
|
inherit (lib) types;
|
|
|
|
cfg = config.dconf;
|
|
|
|
toDconfIni = lib.generators.toINI { mkKeyValue = mkIniKeyValue; };
|
|
|
|
mkIniKeyValue = key: value: "${key}=${toString (lib.hm.gvariant.mkValue value)}";
|
|
|
|
# The dconf keys managed by this configuration. We store this as part of the
|
|
# generation state to be able to reset keys that become unmanaged during
|
|
# switch.
|
|
mkStateDconfKeys =
|
|
nameSuffix: settings:
|
|
pkgs.writeText "dconf-keys${nameSuffix}.json" (
|
|
builtins.toJSON (
|
|
lib.concatLists (
|
|
lib.mapAttrsToList (dir: entries: lib.mapAttrsToList (key: _: "/${dir}/${key}") entries) settings
|
|
)
|
|
)
|
|
);
|
|
|
|
databases =
|
|
lib.optional (cfg.settings != { }) {
|
|
dconfProfile = null;
|
|
stateDconfKeys = mkStateDconfKeys "" cfg.settings;
|
|
inherit (cfg) settings;
|
|
}
|
|
++ lib.mapAttrsToList (name: value: {
|
|
dconfProfile = pkgs.writeText "dconf-profile-${name}" ''
|
|
user-db:${name}
|
|
'';
|
|
stateDconfKeys = mkStateDconfKeys "-${name}" value;
|
|
settings = value;
|
|
}) cfg.databases;
|
|
|
|
in
|
|
{
|
|
meta.maintainers = [ lib.maintainers.rycee ];
|
|
|
|
options = {
|
|
dconf = {
|
|
enable = lib.mkOption {
|
|
type = types.bool;
|
|
# While technically dconf on darwin could work, our activation step
|
|
# requires dbus, which only *lightly* supports Darwin in general, and
|
|
# not at all in the way it's packaged in nixpkgs. Because of this, we
|
|
# just disable dconf for darwin hosts by default.
|
|
# In the future, if someone gets dbus working, this _could_ be
|
|
# re-enabled, unclear whether there's actual value in it though.
|
|
default = !pkgs.stdenv.hostPlatform.isDarwin;
|
|
visible = false;
|
|
description = ''
|
|
Whether to enable dconf settings.Add commentMore actions
|
|
Note, if you use NixOS then you must add
|
|
`programs.dconf.enable = true`
|
|
to your system configuration. Otherwise you will see a systemd error
|
|
message when your configuration is activated.
|
|
'';
|
|
};
|
|
|
|
settings = lib.mkOption {
|
|
type = with types; attrsOf (attrsOf lib.hm.types.gvariant);
|
|
default = { };
|
|
example = lib.literalExpression ''
|
|
{
|
|
"org/gnome/calculator" = {
|
|
button-mode = "programming";
|
|
show-thousands = true;
|
|
base = 10;
|
|
word-size = 64;
|
|
window-position = lib.hm.gvariant.mkTuple [100 100];
|
|
};
|
|
}
|
|
'';
|
|
description = ''
|
|
Settings to write to the dconf configuration system.
|
|
|
|
Note that the database is strongly-typed so you need to use the same types
|
|
as described in the GSettings schema. For example, if an option is of type
|
|
`uint32` (`u`), you need to wrap the number
|
|
using the `lib.hm.gvariant.mkUint32` constructor.
|
|
Otherwise, since Nix integers are implicitly coerced to `int32`
|
|
(`i`), it would get stored in the database as such, and GSettings
|
|
might be confused when loading the setting.
|
|
|
|
You might want to use [dconf2nix](https://github.com/gvolpe/dconf2nix)
|
|
to convert dconf database dumps into compatible Nix expression.
|
|
'';
|
|
};
|
|
databases = lib.mkOption {
|
|
type = with types; attrsOf (attrsOf (attrsOf lib.hm.types.gvariant));
|
|
default = { };
|
|
description = ''
|
|
Settings to write to specific dconf user databases.
|
|
See [](#opt-dconf.settings) for details.
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf (cfg.enable && databases != [ ]) {
|
|
# Make sure the dconf directory exists.
|
|
xdg.configFile."dconf/.keep".source = builtins.toFile "keep" "";
|
|
|
|
home.extraBuilderCommands = ''
|
|
mkdir -p $out/state/
|
|
''
|
|
+ lib.concatMapStrings (db: ''
|
|
ln -s ${db.stateDconfKeys} $out/state/${db.stateDconfKeys.name}
|
|
'') databases;
|
|
|
|
home.activation.dconfSettings = lib.hm.dag.entryAfter [ "installPackages" ] (
|
|
lib.concatMapStrings (
|
|
db:
|
|
let
|
|
iniFile = pkgs.writeText "hm-dconf.ini" (toDconfIni db.settings);
|
|
|
|
statePath = "state/${db.stateDconfKeys.name}";
|
|
|
|
cleanup = pkgs.writeShellScript "dconf-cleanup" ''
|
|
set -euo pipefail
|
|
|
|
${config.lib.bash.initHomeManagerLib}
|
|
|
|
PATH=${
|
|
lib.makeBinPath [
|
|
pkgs.dconf
|
|
pkgs.jq
|
|
]
|
|
}''${PATH:+:}$PATH
|
|
|
|
oldState="$1"
|
|
newState="$2"
|
|
|
|
# Can't do cleanup if we don't know the old state.
|
|
if [[ ! -f $oldState ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Reset all keys that are present in the old generation but not the new
|
|
# one.
|
|
jq -r -n \
|
|
--slurpfile old "$oldState" \
|
|
--slurpfile new "$newState" \
|
|
'($old[] - $new[])[]' \
|
|
| while read -r key; do
|
|
verboseEcho "Resetting dconf key \"$key\""
|
|
run $DCONF_DBUS_RUN_SESSION dconf reset "$key"
|
|
done
|
|
'';
|
|
envCommand = lib.optionalString (db.dconfProfile != null) "env DCONF_PROFILE=${db.dconfProfile}";
|
|
in
|
|
''
|
|
if [[ -v DBUS_SESSION_BUS_ADDRESS ]]; then
|
|
export DCONF_DBUS_RUN_SESSION="${envCommand}"
|
|
else
|
|
export DCONF_DBUS_RUN_SESSION="${pkgs.dbus}/bin/dbus-run-session --dbus-daemon=${pkgs.dbus}/bin/dbus-daemon ${envCommand}"
|
|
fi
|
|
|
|
if [[ -v oldGenPath ]]; then
|
|
${cleanup} \
|
|
"$oldGenPath/${statePath}" \
|
|
"$newGenPath/${statePath}"
|
|
fi
|
|
|
|
run $DCONF_DBUS_RUN_SESSION ${pkgs.dconf}/bin/dconf load / < ${iniFile}
|
|
|
|
unset DCONF_DBUS_RUN_SESSION
|
|
''
|
|
) databases
|
|
);
|
|
};
|
|
}
|