Commit 45ad2cbdcba9
Changed files (1)
modules
laptop-keyboard-inhibit
modules/laptop-keyboard-inhibit/default.nix
@@ -1,15 +1,16 @@
# Automatically inhibit (disable) the laptop's internal keyboard when an
# external keyboard is connected, and re-enable it on disconnect.
#
-# Works with both USB and Bluetooth keyboards via udev rules that write
-# to the kernel's input device `inhibited` sysfs attribute (Linux 5.11+).
+# Uses bluetooth-monitor for Bluetooth keyboards (D-Bus events) and udev
+# rules for USB keyboards. Writes to the kernel's input device `inhibited`
+# sysfs attribute (Linux 5.11+).
#
# Usage:
# services.laptop-keyboard-inhibit = {
# enable = true;
-# # Match by device name (Bluetooth keyboards, or any input device)
+# # Match by device name (uses bluetooth-monitor for BT detection)
# keyboards = [ "Eyelash Corne" ];
-# # Or match USB keyboards by vendor:product ID
+# # Or match USB keyboards by vendor:product ID (uses udev)
# usbKeyboards = [ { vendor = "3297"; product = "1969"; } ];
# };
{
@@ -104,11 +105,72 @@ in
};
config = mkIf cfg.enable {
- services.udev.extraRules = concatStringsSep "\n" (
- lib.filter (s: s != "") [
- nameRules
- usbRules
- ]
- );
+ # USB keyboard detection via udev
+ services.udev.extraRules = mkIf (usbRules != "") usbRules;
+
+ # Bluetooth keyboard detection via bluetooth-monitor
+ systemd.services.bluetooth-keyboard-monitor = mkIf (cfg.keyboards != [ ]) {
+ description = "Monitor Bluetooth keyboards and toggle internal keyboard";
+ after = [ "bluetooth.service" ];
+ requires = [ "bluetooth.service" ];
+ wantedBy = [ "multi-user.target" ];
+
+ serviceConfig = {
+ Type = "simple";
+ Restart = "always";
+ RestartSec = 5;
+ };
+
+ script =
+ let
+ # Get Bluetooth MAC addresses for configured keyboard names
+ # User needs to pair keyboards first with bluetoothctl
+ getDeviceScript = pkgs.writeShellScript "get-bt-devices" ''
+ # Wait for bluetooth to be ready
+ sleep 2
+
+ # Find MAC addresses for configured keyboard names
+ ${concatMapStringsSep "\n" (name: ''
+ MAC=$(bluetoothctl devices | grep -i "${name}" | awk '{print $2}' | head -1)
+ if [ -n "$MAC" ]; then
+ echo "$MAC"
+ fi
+ '') cfg.keyboards}
+ '';
+ in
+ ''
+ set -euo pipefail
+
+ # Get MAC addresses of configured keyboards
+ MACS=$(${getDeviceScript})
+
+ if [ -z "$MACS" ]; then
+ echo "No Bluetooth keyboards found. Make sure they are paired."
+ echo "Use: bluetoothctl pair <MAC>"
+ sleep 10
+ exit 1
+ fi
+
+ # Monitor each keyboard
+ while IFS= read -r MAC; do
+ (
+ echo "Monitoring Bluetooth keyboard: $MAC"
+ while true; do
+ if bluetoothctl info "$MAC" 2>/dev/null | grep -q "Connected: yes"; then
+ # Keyboard connected - disable internal keyboard
+ ${toggleScript} inhibit
+ else
+ # Keyboard disconnected - enable internal keyboard
+ ${toggleScript} uninhibit
+ fi
+ sleep 5
+ done
+ ) &
+ done <<< "$MACS"
+
+ # Wait for all background monitors
+ wait
+ '';
+ };
};
}