macbook: add DWT daemon for bcm5974 touchpad

Hyprland's built-in disable-while-typing doesn't work on this
MacBook because the keyboard and touchpad share the same USB
device, breaking libinput's device pairing. Add a lightweight
Python daemon that watches keyboard events and inhibits the
touchpad via sysfs for 500ms after each keypress.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
rope 2026-05-18 17:30:00 +01:00
parent 2ed677bd8f
commit 8285fce24a

View file

@ -32,6 +32,66 @@
HandleLidSwitchExternalPower = "suspend"; HandleLidSwitchExternalPower = "suspend";
}; };
# Disable-while-typing daemon for the bcm5974 touchpad.
# Hyprland's built-in DWT doesn't work because the keyboard and
# touchpad share the same USB device, breaking libinput's pairing.
systemd.services.macbook-dwt = {
description = "Disable touchpad while typing (bcm5974)";
after = [ "systemd-udevd.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
Restart = "on-failure";
RestartSec = 3;
ExecStart = "${pkgs.python3.withPackages (p: [])}/bin/python3 ${pkgs.writeText "macbook-dwt.py" ''
import glob, os, select, struct, time
EVENT_SIZE = struct.calcsize("llHHi")
EV_KEY = 0x01
DWT_TIMEOUT = 0.5
def find_event(name):
for p in sorted(glob.glob("/sys/class/input/event*/device/name")):
with open(p) as f:
if name in f.read():
return p.split("/")[4]
return None
def main():
tp = find_event("bcm5974")
kb = find_event("Apple Internal Keyboard")
if not tp or not kb:
raise SystemExit(f"Devices not found: touchpad={tp}, keyboard={kb}")
inhibit = f"/sys/class/input/{tp}/device/inhibited"
active = False
last_key = 0.0
with open(f"/dev/input/{kb}", "rb") as f:
try:
while True:
timeout = max(0, DWT_TIMEOUT - (time.monotonic() - last_key)) if active else None
r, _, _ = select.select([f], [], [], timeout)
if r:
data = os.read(f.fileno(), EVENT_SIZE * 64)
for off in range(0, len(data) - EVENT_SIZE + 1, EVENT_SIZE):
_, _, typ, _, val = struct.unpack("llHHi", data[off:off + EVENT_SIZE])
if typ == EV_KEY and val:
last_key = time.monotonic()
if not active:
open(inhibit, "w").write("1")
active = True
if active and time.monotonic() - last_key >= DWT_TIMEOUT:
open(inhibit, "w").write("0")
active = False
finally:
open(inhibit, "w").write("0")
main()
''}";
};
};
home-manager.users.fred = { pkgs, ... }: { home-manager.users.fred = { pkgs, ... }: {
wayland.windowManager.hyprland.settings.monitor = [{ wayland.windowManager.hyprland.settings.monitor = [{
output = ""; output = "";