mirror of
https://github.com/LnL7/nix-darwin.git
synced 2024-12-14 11:57:34 +00:00
114 lines
5.3 KiB
Nix
114 lines
5.3 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.services.karabiner-elements;
|
|
|
|
parentAppDir = "/Applications/.Nix-Karabiner";
|
|
in
|
|
|
|
{
|
|
options.services.karabiner-elements = {
|
|
enable = mkEnableOption "Karabiner-Elements";
|
|
package = mkPackageOption pkgs "karabiner-elements" { };
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
environment.systemPackages = [ cfg.package ];
|
|
|
|
system.activationScripts.preActivation.text = ''
|
|
rm -rf ${parentAppDir}
|
|
mkdir -p ${parentAppDir}
|
|
# Kernel extensions must reside inside of /Applications, they cannot be symlinks
|
|
cp -r ${cfg.package.driver}/Applications/.Karabiner-VirtualHIDDevice-Manager.app ${parentAppDir}
|
|
'';
|
|
|
|
system.activationScripts.postActivation.text = ''
|
|
echo "attempt to activate karabiner system extension and start daemons" >&2
|
|
launchctl unload /Library/LaunchDaemons/org.nixos.start_karabiner_daemons.plist
|
|
launchctl load -w /Library/LaunchDaemons/org.nixos.start_karabiner_daemons.plist
|
|
'';
|
|
|
|
# We need the karabiner_grabber and karabiner_observer daemons to run after the
|
|
# Nix Store has been mounted, but we can't use wait4path as they need to be
|
|
# executed directly for the Input Monitoring permission. We also want these
|
|
# daemons to auto restart but if they start up without the Nix Store they will
|
|
# refuse to run again until they've been unloaded and loaded back in so we can
|
|
# use a helper daemon to start them. We also only want to run the daemons after
|
|
# the system extension is activated, so we can call activate from the manager
|
|
# which will block until the system extension is activated.
|
|
launchd.daemons.start_karabiner_daemons = {
|
|
script = ''
|
|
${parentAppDir}/.Karabiner-VirtualHIDDevice-Manager.app/Contents/MacOS/Karabiner-VirtualHIDDevice-Manager activate
|
|
launchctl kickstart system/org.pqrs.karabiner.karabiner_grabber
|
|
launchctl kickstart system/org.pqrs.karabiner.karabiner_observer
|
|
'';
|
|
serviceConfig.Label = "org.nixos.start_karabiner_daemons";
|
|
serviceConfig.RunAtLoad = true;
|
|
};
|
|
|
|
launchd.daemons.karabiner_grabber = {
|
|
serviceConfig.ProgramArguments = [
|
|
"${cfg.package}/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_grabber"
|
|
];
|
|
serviceConfig.ProcessType = "Interactive";
|
|
serviceConfig.Label = "org.pqrs.karabiner.karabiner_grabber";
|
|
serviceConfig.KeepAlive.SuccessfulExit = true;
|
|
serviceConfig.KeepAlive.Crashed = true;
|
|
serviceConfig.KeepAlive.AfterInitialDemand = true;
|
|
};
|
|
|
|
launchd.daemons.karabiner_observer = {
|
|
serviceConfig.ProgramArguments = [
|
|
"${cfg.package}/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_observer"
|
|
];
|
|
|
|
serviceConfig.Label = "org.pqrs.karabiner.karabiner_observer";
|
|
serviceConfig.KeepAlive.SuccessfulExit = true;
|
|
serviceConfig.KeepAlive.Crashed = true;
|
|
serviceConfig.KeepAlive.AfterInitialDemand = true;
|
|
};
|
|
|
|
launchd.daemons.Karabiner-DriverKit-VirtualHIDDeviceClient = {
|
|
command = "\"${cfg.package.driver}/Library/Application Support/org.pqrs/Karabiner-DriverKit-VirtualHIDDevice/Applications/Karabiner-DriverKit-VirtualHIDDeviceClient.app/Contents/MacOS/Karabiner-DriverKit-VirtualHIDDeviceClient\"";
|
|
serviceConfig.ProcessType = "Interactive";
|
|
serviceConfig.Label = "org.pqrs.Karabiner-DriverKit-VirtualHIDDeviceClient";
|
|
serviceConfig.KeepAlive = true;
|
|
};
|
|
|
|
# Normally karabiner_console_user_server calls activate on the manager but
|
|
# because we use a custom location we need to call activate manually.
|
|
launchd.user.agents.activate_karabiner_system_ext = {
|
|
serviceConfig.ProgramArguments = [
|
|
"${parentAppDir}/.Karabiner-VirtualHIDDevice-Manager.app/Contents/MacOS/Karabiner-VirtualHIDDevice-Manager" "activate"
|
|
];
|
|
serviceConfig.RunAtLoad = true;
|
|
};
|
|
|
|
# We need this to run every reboot as /run gets nuked so we can't put this
|
|
# inside the preActivation script as it only gets run on darwin-rebuild switch.
|
|
launchd.daemons.setsuid_karabiner_session_monitor = {
|
|
script = ''
|
|
rm -rf /run/wrappers
|
|
mkdir -p /run/wrappers/bin
|
|
install -m4555 "${cfg.package}/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_session_monitor" /run/wrappers/bin
|
|
'';
|
|
serviceConfig.RunAtLoad = true;
|
|
serviceConfig.KeepAlive.SuccessfulExit = false;
|
|
};
|
|
|
|
launchd.user.agents.karabiner_session_monitor = {
|
|
serviceConfig.ProgramArguments = [
|
|
"/bin/sh" "-c"
|
|
"/bin/wait4path /run/wrappers/bin && /run/wrappers/bin/karabiner_session_monitor"
|
|
];
|
|
serviceConfig.Label = "org.pqrs.karabiner.karabiner_session_monitor";
|
|
serviceConfig.KeepAlive = true;
|
|
};
|
|
|
|
environment.userLaunchAgents."org.pqrs.karabiner.agent.karabiner_grabber.plist".source = "${cfg.package}/Library/LaunchAgents/org.pqrs.karabiner.agent.karabiner_grabber.plist";
|
|
environment.userLaunchAgents."org.pqrs.karabiner.agent.karabiner_observer.plist".source = "${cfg.package}/Library/LaunchAgents/org.pqrs.karabiner.agent.karabiner_observer.plist";
|
|
environment.userLaunchAgents."org.pqrs.karabiner.karabiner_console_user_server.plist".source = "${cfg.package}/Library/LaunchAgents/org.pqrs.karabiner.karabiner_console_user_server.plist";
|
|
};
|
|
}
|