diff --git a/src/hhd/controller/lib/hide.py b/src/hhd/controller/lib/hide.py index ac27b231..e47d372f 100644 --- a/src/hhd/controller/lib/hide.py +++ b/src/hhd/controller/lib/hide.py @@ -199,10 +199,18 @@ def unhide_all(): except Exception: pass - if not removed: + # Always trigger udev reload if we removed rules OR have hidden devices + if removed or _hidden: + # We have to reload affected devices if we removed rules + for parent in _hidden: + reload_children(parent) + + # If no specific devices to reload but we removed rules, reload all input devices + if removed and not _hidden: + subprocess.run(["udevadm", "trigger", "--subsystem-match=input"], capture_output=True) + subprocess.run(["udevadm", "settle"], capture_output=True) + + _hidden.clear() return True - # We have to reload affected devices if we removed rules - for parent in _hidden: - reload_children(parent) - _hidden.clear() \ No newline at end of file + return True \ No newline at end of file diff --git a/src/hhd/controller/physical/evdev.py b/src/hhd/controller/physical/evdev.py index 1b455350..31a00e50 100644 --- a/src/hhd/controller/physical/evdev.py +++ b/src/hhd/controller/physical/evdev.py @@ -350,6 +350,12 @@ def open(self) -> Sequence[int]: def close(self, exit: bool) -> bool: if self.dev: + try: + if self.grab: + self.dev.ungrab() + except Exception as e: + logger.warning(f"Failed to ungrab device {self.dev.path}: {e}") + if self.hidden and exit: unhide_gamepad(self.dev.path, self.hidden) self.dev.close() diff --git a/src/hhd/device/claw/base.py b/src/hhd/device/claw/base.py index eb9906cc..2ace1927 100644 --- a/src/hhd/device/claw/base.py +++ b/src/hhd/device/claw/base.py @@ -455,21 +455,25 @@ def controller_loop( btn_map=dconf.get("btn_mapping", MSI_CLAW_MAPPINGS), ) - # Mute these so after suspend we do not get stray keypresses + # Desktop detectors with dynamic grabbing d_kbd_2 = DesktopDetectorEvdev( vid=[MSI_CLAW_VID], pid=[MSI_CLAW_XINPUT_PID, MSI_CLAW_DINPUT_PID], required=False, - grab=True, + grab=False, # Start without grabbing, grab dynamically when needed capabilities={EC("EV_KEY"): [EC("KEY_ESC")]}, ) d_mouse = DesktopDetectorEvdev( vid=[MSI_CLAW_VID], pid=[MSI_CLAW_XINPUT_PID, MSI_CLAW_DINPUT_PID], required=False, - grab=True, + grab=False, # Start without grabbing, grab dynamically when needed capabilities={EC("EV_KEY"): [EC("BTN_MOUSE")]}, ) + + # Track grabbing state for desktop detectors + d_kbd_2_grabbed = False + d_mouse_grabbed = False kargs = {} @@ -559,6 +563,22 @@ def prepare(m): if id(d) in to_run: evs.extend(d.produce(r)) + # Dynamic grabbing for desktop detectors + # Only grab when we need to detect desktop events, release when not needed + if not d_kbd_2_grabbed and d_kbd_2.dev: + try: + d_kbd_2.dev.grab() + d_kbd_2_grabbed = True + except Exception: + pass # Ignore grab failures, continue without grabbing + + if not d_mouse_grabbed and d_mouse.dev: + try: + d_mouse.dev.grab() + d_mouse_grabbed = True + except Exception: + pass # Ignore grab failures, continue without grabbing + # Detect if we are in desktop mode through events desktop_mode = d_mouse.desktop or d_kbd_2.desktop d_mouse.desktop = False diff --git a/src/hhd/plugins/powerbutton/const.py b/src/hhd/plugins/powerbutton/const.py index 2b72f2a8..b5231eaf 100644 --- a/src/hhd/plugins/powerbutton/const.py +++ b/src/hhd/plugins/powerbutton/const.py @@ -84,6 +84,7 @@ class PowerButtonConfig(NamedTuple): "MSI Claw A8", "Claw A8 BZ2EM", type="only_press", + phys=["gpio-keys", "LNXPWRBN", "PNP0C0C"], ), ]