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:
parent
2ed677bd8f
commit
8285fce24a
1 changed files with 60 additions and 0 deletions
|
|
@ -32,6 +32,66 @@
|
|||
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, ... }: {
|
||||
wayland.windowManager.hyprland.settings.monitor = [{
|
||||
output = "";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue