xidlehook_core/modules/
mod.rs

1//! The module trait and some useful implementations such as
2//! combinators
3
4use crate::{Error, Result, TimerInfo};
5
6use log::warn;
7
8/// A decision each module has to take before a timer is executed:
9/// Should it be?
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
11pub enum Progress {
12    /// Continue the program, no action taken.
13    Continue,
14    /// Abort this chain, don't pursue it any longer. The timers won't be
15    /// checked again, until the user is active.
16    Abort,
17    /// Like abort, but is immediately ready to check timers again. See
18    /// https://github.com/jD91mZM2/xidlehook/issues/43 for a quick description
19    /// of why this exists: When an application goes out of fullscreen, you
20    /// don't want to re-check it all the time. But an application can stop
21    /// playing audio without user interaction.
22    Reset,
23    /// Stop the program completely. Use this sparingly.
24    Stop,
25}
26
27/// A generic module that controls whether timers should execute or
28/// not (outside of the normal timer)
29pub trait Module {
30    /// Decides if a timer should be allowed to execute
31    fn pre_timer(&mut self, _timer: TimerInfo) -> Result<Progress> {
32        Ok(Progress::Continue)
33    }
34
35    /// Decides what happens after a timer has executed
36    fn post_timer(&mut self, _timer: TimerInfo) -> Result<Progress> {
37        Ok(Progress::Continue)
38    }
39
40    /// Is called when there's a potentially recoverable error. Can
41    /// re-throw an unrecoverable error.
42    fn warning(&mut self, _error: &Error) -> Result<()> {
43        Ok(())
44    }
45
46    /// If this is called, the counting was reset - clear any cache
47    /// here
48    fn reset(&mut self) -> Result<()> {
49        Ok(())
50    }
51}
52
53/// The default module is also the unit type because why not
54impl Module for () {
55    fn warning(&mut self, error: &Error) -> Result<()> {
56        warn!("{} (Debug: {:?})", error, error);
57        Ok(())
58    }
59}
60
61impl Module for Box<dyn Module> {
62    fn pre_timer(&mut self, timer: TimerInfo) -> Result<Progress> {
63        (&mut **self).pre_timer(timer)
64    }
65    fn post_timer(&mut self, timer: TimerInfo) -> Result<Progress> {
66        (&mut **self).post_timer(timer)
67    }
68    fn warning(&mut self, error: &Error) -> Result<()> {
69        (&mut **self).warning(error)
70    }
71    fn reset(&mut self) -> Result<()> {
72        (&mut **self).reset()
73    }
74}
75
76/// Combine two timers using the type-system. Can be recursed for a
77/// fixed-size amount of timers. Similar to iterator.chain.
78impl<A, B> Module for (A, B)
79where
80    A: Module,
81    B: Module,
82{
83    fn pre_timer(&mut self, timer: TimerInfo) -> Result<Progress> {
84        let status = self.0.pre_timer(timer)?;
85        if status != Progress::Continue {
86            return Ok(status);
87        }
88        self.1.pre_timer(timer)
89    }
90    fn post_timer(&mut self, timer: TimerInfo) -> Result<Progress> {
91        let status = self.0.post_timer(timer)?;
92        if status != Progress::Continue {
93            return Ok(status);
94        }
95        self.1.post_timer(timer)
96    }
97    fn warning(&mut self, error: &Error) -> Result<()> {
98        self.0.warning(error)?;
99        self.1.warning(error)
100    }
101    fn reset(&mut self) -> Result<()> {
102        self.0.reset()?;
103        self.1.reset()
104    }
105}
106
107/// Combine multiple modules with a dynamic size
108impl<M: Module> Module for Vec<M> {
109    fn pre_timer(&mut self, timer: TimerInfo) -> Result<Progress> {
110        for module in self {
111            let status = module.pre_timer(timer)?;
112            if status != Progress::Continue {
113                return Ok(status);
114            }
115        }
116        Ok(Progress::Continue)
117    }
118    fn post_timer(&mut self, timer: TimerInfo) -> Result<Progress> {
119        for module in self {
120            let status = module.post_timer(timer)?;
121            if status != Progress::Continue {
122                return Ok(status);
123            }
124        }
125        Ok(Progress::Continue)
126    }
127    fn warning(&mut self, error: &Error) -> Result<()> {
128        for module in self {
129            module.warning(error)?;
130        }
131        Ok(())
132    }
133    fn reset(&mut self) -> Result<()> {
134        for module in self {
135            module.reset()?;
136        }
137        Ok(())
138    }
139}
140
141#[cfg(feature = "pulse")]
142pub mod pulse;
143pub mod stop_at;
144pub mod xcb;
145
146#[cfg(feature = "pulse")]
147pub use self::pulse::NotWhenAudio;
148pub use self::{stop_at::StopAt, xcb::Xcb};