Skip to content

feat(daemon): Windows lid auto-pause via SystemEvents.PowerModeChanged - #22

Merged
scokeepa merged 1 commit into
masterfrom
feat/windows-lid-auto-pause
Apr 15, 2026
Merged

feat(daemon): Windows lid auto-pause via SystemEvents.PowerModeChanged#22
scokeepa merged 1 commit into
masterfrom
feat/windows-lid-auto-pause

Conversation

@scokeepa

Copy link
Copy Markdown
Owner

Summary

  • Subscribes cmux-daemon to SystemEvents.PowerModeChanged and toggles %TEMP%\cmux-paused.flag on Suspend/Resume.
  • New file src/Cmux.Daemon/LidPauseWatcher.cs; one-line hookup in Program.cs; Microsoft.Win32.SystemEvents 9.0.0 added to Cmux.Daemon.csproj.
  • The flag file is the cross-platform SSOT shared with cmuxO PR #5 (macOS sleepwatcher via ~/.sleep / ~/.wakeup). Orchestration skills poll this single file on both platforms.

Why here (daemon, not WPF app)

cmux-daemon is the always-on background process. Hooking there means lid events are captured even when no WPF window is open, and the logic stays out of UI code.

Why SystemEvents.PowerModeChanged

  • Built-in managed message pump — no hidden NativeWindow, no WM_POWERBROADCAST P/Invoke.
  • Fires for sleep/hibernate/resume regardless of lid vs Start-menu sleep.
  • Package Microsoft.Win32.SystemEvents is the supported path for non-WinForms/WPF executables on net*-windows.

Alternative considered: PowerRegisterSuspendResumeNotification (powrprof.dll) — rejected for complexity; no advantage for this use case.

Test plan

  • dotnet build Cmux.sln -c Debug succeeds on Windows (unverified — authored on macOS, no local .NET 10 Windows SDK).
  • Start cmux-daemon, close laptop lid / trigger Sleep → %TEMP%\cmux-paused.flag exists; daemon-debug.log shows [lid-watcher] Suspend.
  • Resume → flag removed; log shows [lid-watcher] Resume.
  • Hibernate/Resume cycle → same behavior.
  • Kill daemon with flag present → orphaned flag is cleaned by next Resume (acceptable: worst case a stale flag until next suspend/resume).

Risks / follow-up

  • Unverified build: authored on macOS; reviewer please confirm net10.0-windows resolves Microsoft.Win32.SystemEvents 9.0.0 cleanly (may want to pin to 10.0.0 once published to match TFM).
  • Stale flag on crash: if the daemon crashes between Suspend and Resume, the flag persists. Could add a startup cleanup (File.Delete(FlagPath) before LidPauseWatcher.Start) if this proves annoying in practice — left out of this PR to keep it minimal.
  • Single-instance mutex: existing Global\CmuxDaemon mutex ensures only one subscriber, so no duplicate flag toggling.

🤖 Generated with Claude Code

Subscribes the always-running cmux-daemon to PowerModeChanged and
toggles %TEMP%\cmux-paused.flag on Suspend/Resume. The flag is the
cross-platform SSOT shared with cmuxO (macOS sleepwatcher hook), so
orchestration skills can pause/resume worker activity uniformly on
both platforms.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@scokeepa
scokeepa merged commit e883f2d into master Apr 15, 2026
2 checks passed
@scokeepa
scokeepa deleted the feat/windows-lid-auto-pause branch April 15, 2026 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant