15
15
16
16
#[ derive( Debug , thiserror:: Error ) ]
17
17
pub enum SleepInhibitError {
18
+ #[ cfg( target_os = "linux" ) ]
18
19
#[ error( "D-Bus connection failed: {0}" ) ]
19
20
DBusConnection ( #[ from] dbus:: Error ) ,
20
21
#[ error( "Power management API failed: {0}" ) ]
@@ -96,6 +97,16 @@ mod linux_impl {
96
97
_fd : OwnedFd ,
97
98
}
98
99
100
+ /// See https://www.freedesktop.org/wiki/Software/systemd/inhibit/
101
+ /// The Inhibit method takes four arguments:
102
+ /// - what: "sleep" indicates we want to prevent sleep/suspend
103
+ /// - who: The application name requesting the inhibition
104
+ /// - why: Human-readable reason for the inhibition
105
+ /// - mode: "block" completely blocks sleep, "delay" only delays it
106
+ ///
107
+ /// Returns a file descriptor that must be kept open to maintain the
108
+ /// inhibition. The FD is closed automatically when this value is
109
+ /// dropped.
99
110
impl LinuxGuard {
100
111
pub fn new ( app_name : & str , reason : & str ) -> Result < Self , SleepInhibitError > {
101
112
let conn = Connection :: new_system ( ) . map_err ( SleepInhibitError :: DBusConnection ) ?;
@@ -125,15 +136,30 @@ mod linux_impl {
125
136
mod windows_impl {
126
137
use super :: * ;
127
138
139
+ /// Informs the system that the state being set should remain in effect
140
+ /// until the next call that uses ES_CONTINUOUS and one of the other
141
+ /// state flags is cleared.
142
+ const ES_CONTINUOUS : u32 = 0x80000000 ;
143
+
144
+ /// Forces the system to be in the working state by resetting the system
145
+ /// idle timer.
146
+ const ES_SYSTEM_REQUIRED : u32 = 0x00000001 ;
147
+
128
148
pub struct WindowsGuard ;
129
149
150
+ /// See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate
151
+ /// SetThreadExecutionState modifies the system's sleep timer behavior.
152
+ /// Parameters used:
153
+ /// - ES_CONTINUOUS (0x80000000): State remains in effect until the next
154
+ /// call
155
+ /// - ES_SYSTEM_REQUIRED (0x00000001): Forces the system to stay in working
156
+ /// state
157
+ ///
158
+ /// The system is automatically allowed to sleep again when this guard is
159
+ /// dropped by clearing ES_SYSTEM_REQUIRED while maintaining
160
+ /// ES_CONTINUOUS.
130
161
impl WindowsGuard {
131
162
pub fn new ( _app : & str , _reason : & str ) -> Result < Self , SleepInhibitError > {
132
- // Map scope to execution state flags.
133
- // ES_CONTINUOUS is always set to make the request sticky for this call.
134
- const ES_CONTINUOUS : u32 = 0x80000000 ;
135
- const ES_SYSTEM_REQUIRED : u32 = 0x00000001 ;
136
-
137
163
let flags: u32 = ES_CONTINUOUS | ES_SYSTEM_REQUIRED ;
138
164
139
165
// SAFETY: Calling documented Windows API with constant flags.
@@ -150,7 +176,6 @@ mod windows_impl {
150
176
impl Drop for WindowsGuard {
151
177
fn drop ( & mut self ) {
152
178
// Clear the requirement and keep ES_CONTINUOUS.
153
- const ES_CONTINUOUS : u32 = 0x80000000 ;
154
179
// SAFETY: Restoring to a benign state.
155
180
unsafe {
156
181
windows_sys:: Win32 :: System :: Power :: SetThreadExecutionState ( ES_CONTINUOUS ) ;
@@ -191,9 +216,20 @@ mod mac_impl {
191
216
id : IOPMAssertionID ,
192
217
}
193
218
219
+ /// See https://developer.apple.com/documentation/iokit/1557134-IOPMAssertionCreateWithName
220
+ /// IOPMAssertionCreateWithName creates a power assertion that prevents
221
+ /// system sleep. Parameters:
222
+ /// - assertion_type: "PreventSystemSleep" prevents the entire system from
223
+ /// sleeping
224
+ /// - level: 255 (kIOPMAssertionLevelOn) activates the assertion
225
+ /// - assertion_name: A human-readable reason for the assertion
226
+ /// - assertion_id: Returns an ID that must be released to remove the
227
+ /// assertion
228
+ ///
229
+ /// The assertion is automatically released when this guard is dropped.
194
230
impl MacGuard {
195
231
pub fn new ( _app : & str , why : & str ) -> anyhow:: Result < Self > {
196
- let assertion_type = "NoIdleSleepAssertion " ;
232
+ let assertion_type = "PreventSystemSleep " ;
197
233
198
234
let mut id: IOPMAssertionID = 0 ;
199
235
// SAFETY: FFI call with well-formed CFStrings that live across the call.
0 commit comments