#![allow(clippy::uninlined_format_args)]
use crossbeam_channel::{unbounded, Receiver, Sender};
use once_cell::sync::{Lazy, OnceCell};
mod error;
pub mod hotkey;
mod platform_impl;
pub use self::error::*;
use hotkey::HotKey;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum HotKeyState {
Pressed,
Released,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct GlobalHotKeyEvent {
pub id: u32,
pub state: HotKeyState,
}
pub type GlobalHotKeyEventReceiver = Receiver<GlobalHotKeyEvent>;
type GlobalHotKeyEventHandler = Box<dyn Fn(GlobalHotKeyEvent) + Send + Sync + 'static>;
static GLOBAL_HOTKEY_CHANNEL: Lazy<(Sender<GlobalHotKeyEvent>, GlobalHotKeyEventReceiver)> =
Lazy::new(unbounded);
static GLOBAL_HOTKEY_EVENT_HANDLER: OnceCell<Option<GlobalHotKeyEventHandler>> = OnceCell::new();
impl GlobalHotKeyEvent {
pub fn id(&self) -> u32 {
self.id
}
pub fn state(&self) -> HotKeyState {
self.state
}
pub fn receiver<'a>() -> &'a GlobalHotKeyEventReceiver {
&GLOBAL_HOTKEY_CHANNEL.1
}
pub fn set_event_handler<F: Fn(GlobalHotKeyEvent) + Send + Sync + 'static>(f: Option<F>) {
if let Some(f) = f {
let _ = GLOBAL_HOTKEY_EVENT_HANDLER.set(Some(Box::new(f)));
} else {
let _ = GLOBAL_HOTKEY_EVENT_HANDLER.set(None);
}
}
pub(crate) fn send(event: GlobalHotKeyEvent) {
if let Some(handler) = GLOBAL_HOTKEY_EVENT_HANDLER.get_or_init(|| None) {
handler(event);
} else {
let _ = GLOBAL_HOTKEY_CHANNEL.0.send(event);
}
}
}
pub struct GlobalHotKeyManager {
platform_impl: platform_impl::GlobalHotKeyManager,
}
impl GlobalHotKeyManager {
pub fn new() -> crate::Result<Self> {
Ok(Self {
platform_impl: platform_impl::GlobalHotKeyManager::new()?,
})
}
pub fn register(&self, hotkey: HotKey) -> crate::Result<()> {
self.platform_impl.register(hotkey)
}
pub fn unregister(&self, hotkey: HotKey) -> crate::Result<()> {
self.platform_impl.unregister(hotkey)
}
pub fn register_all(&self, hotkeys: &[HotKey]) -> crate::Result<()> {
self.platform_impl.register_all(hotkeys)?;
Ok(())
}
pub fn unregister_all(&self, hotkeys: &[HotKey]) -> crate::Result<()> {
self.platform_impl.unregister_all(hotkeys)?;
Ok(())
}
}