1
use ashpd::Error;
2
use ashpd::desktop::Session;
3
use ashpd::desktop::global_shortcuts::{Activated, GlobalShortcuts, NewShortcut};
4
use futures_util::Stream;
5
use std::sync::Arc;
6
use tokio::sync::Mutex;
7

            
8
/// Wrapper around GlobalShortcuts
9
#[derive(Clone)]
10
pub struct HotkeyPortal {
11
    portal: Arc<Mutex<GlobalShortcuts>>,
12
    session: Arc<Mutex<Session<GlobalShortcuts>>>,
13
}
14

            
15
impl HotkeyPortal {
16
    /// Register a global hotkey to trigger the autoclicker.
17
    pub async fn register() -> Result<Self, Error> {
18
        let portal = GlobalShortcuts::new().await?;
19
        let session = portal.create_session(Default::default()).await?;
20
        let hotkey = NewShortcut::new("Turbo Clicker Trigger", "Start/stop the autoclicker")
21
            .preferred_trigger("CTRL+SHIFT+F12");
22
        portal
23
            .bind_shortcuts(&session, &[hotkey], None, Default::default())
24
            .await?;
25
        Ok(Self {
26
            portal: Arc::new(Mutex::new(portal)),
27
            session: Arc::new(Mutex::new(session)),
28
        })
29
    }
30
    /// Return a stream of Activated events when the hotkey is pressed.
31
    pub async fn activated_stream(&self) -> Result<impl Stream<Item = Activated>, Error> {
32
        let portal = self.portal.lock().await;
33
        portal.receive_activated().await
34
    }
35
    /// Open dialog to configure the hotkey.
36
    pub async fn configure_hotkey(&self) {
37
        let portal = self.portal.lock().await;
38
        let session = self.session.lock().await;
39
        match portal
40
            .configure_shortcuts(&session, None, Default::default())
41
            .await
42
        {
43
            Ok(_) => (),
44
            Err(e) => eprintln!("Failed to open hotkey configuration dialog: {e}"),
45
        };
46
    }
47
}