keep_active/
lib.rs

1//! Keep your computer awake.
2//!
3//! # Examples
4//!
5//! ```
6//! # fn try_main() -> anyhow::Result<()> {
7//! let _awake = keep_active::Builder::default()
8//!     .display(true)
9//!     .reason("Video playback")
10//!     .app_name("My prog")
11//!     .app_reverse_domain("io.github.myprog")
12//!     .create()?;
13//! # Ok(())
14//! # }
15//! # try_main();
16//! ```
17//!
18//! ```
19//! # fn try_main() -> anyhow::Result<()> {
20//! let _awake = keep_active::Builder::default()
21//!     .display(true)
22//!     .idle(true)
23//!     .sleep(true)
24//!     .create()?;
25//! # Ok(())
26//! # }
27//! # try_main();
28//! ```
29
30use anyhow::Result;
31use derive_builder::Builder;
32use enigo::{Enigo, Key, KeyboardControllable, MouseControllable};
33use std::{thread, time::Duration};
34
35mod sys;
36
37#[derive(Builder, Debug)]
38#[builder(public, name = "Builder", build_fn(private))]
39#[allow(dead_code)] // Some fields are unused on some platforms
40struct Options {
41    /// Prevent the display from turning off.
42    #[builder(default)]
43    display: bool,
44
45    /// Prevent the system from sleeping due to idleness.
46    #[builder(default)]
47    idle: bool,
48
49    /// Prevent the system from sleeping. Only works under certain, OS dependant, conditions.
50    #[builder(default)]
51    sleep: bool,
52
53    // TODO Reconsider this defaults. They are really meant for the CLI.
54    /// Reason the consumer is keeping the system awake. Defaults to `"User requested"`. (Used on Linux & macOS)
55    #[builder(setter(into), default = "\"User requested\".to_string()")]
56    reason: String,
57
58    /// Name of the program keeping the system awake. Defaults to `"keep-active"`. (Used on Linux)
59    #[builder(setter(into), default = "\"keep-active\".to_string()")]
60    app_name: String,
61
62    /// Reverse domain name of the program keeping the system awake. Defaults to `"io.github.omerbustun.keep-active"`. (Used on Linux)
63    #[builder(
64        setter(into),
65        default = "\"io.github.omerbustun.keep-active\".to_string()"
66    )]
67    app_reverse_domain: String,
68}
69
70impl Builder {
71    pub fn create(&self) -> Result<KeepActive> {
72        Ok(KeepActive {
73            _imp: sys::KeepActive::new(self.build()?)?,
74        })
75    }
76}
77
78/// Keeps the machine or display awake (as configured), until dropped. Create using [struct@Builder].
79pub struct KeepActive {
80    _imp: sys::KeepActive,
81}
82
83// TODO: exit gracefully on Ctrl+C
84pub fn simulate_activity() -> Result<(), Box<dyn std::error::Error>> {
85    let mut enigo = Enigo::new();
86    let step_count = 20; // Increase for smoother circle
87    let radius = 1.0; // Radius for 2 pixel diameter circle
88
89    loop {
90        for i in 0..step_count {
91            let angle = 2.0 * std::f64::consts::PI * (i as f64) / (step_count as f64);
92            let x = (radius * angle.cos()).round() as i32;
93            let y = (radius * angle.sin()).round() as i32;
94            enigo.mouse_move_relative(x, y);
95            thread::sleep(Duration::from_millis(100));
96        }
97
98        // Simulate a key press to keep activity
99        enigo.key_down(Key::Shift);
100        enigo.key_up(Key::Shift);
101
102        thread::sleep(Duration::from_secs(60)); // TODO: Make this configurable
103    }
104}