#![allow(clippy::doc_lazy_continuation)]
#[cfg(windows)]
pub mod error;
#[cfg(all(windows, feature = "thread_safe"))]
pub mod global;
#[cfg(windows)]
pub mod keys;
#[cfg(windows)]
pub mod single_thread;
#[cfg(all(windows, feature = "thread_safe"))]
pub mod thread_safe;
use core::fmt;
#[cfg(all(windows, feature = "thread_safe"))]
pub use thread_safe::HotkeyManager;
#[cfg(all(windows, not(feature = "thread_safe")))]
pub use single_thread::HotkeyManager;
#[cfg(windows)]
use windows_sys::Win32::Foundation::HWND;
#[cfg(windows)]
use windows_sys::Win32::UI::WindowsAndMessaging::{PostMessageW, WM_NULL};
#[cfg(windows)]
use crate::error::HotkeyError;
#[cfg(windows)]
use crate::keys::*;
#[cfg(windows)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct HotkeyId(u16);
#[cfg(windows)]
struct HotkeyCallback<T> {
callback: Option<Box<dyn Fn() -> T + 'static>>,
extra_keys: Option<Vec<VirtualKey>>,
}
#[cfg(windows)]
impl<T> fmt::Debug for HotkeyCallback<T>
where
T: fmt::Debug, {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HotkeyCallback")
.field(
"callback",
&self.callback.as_ref().map_or_else(
|| "None".to_string(),
|_| "Some(Fn() -> T + 'static)".to_string(),
),
)
.field("extra_keys", &self.extra_keys)
.finish()
}
}
#[cfg(windows)]
pub trait HotkeyManagerImpl<T> {
fn new() -> Self;
fn register_extrakeys(
&mut self,
virtual_key: VirtualKey,
modifiers_key: Option<&[ModifiersKey]>,
extra_keys: Option<&[VirtualKey]>,
callback: Option<impl Fn() -> T + Send + 'static>,
) -> Result<HotkeyId, HotkeyError>;
fn register(
&mut self,
virtual_key: VirtualKey,
modifiers_key: Option<&[ModifiersKey]>,
callback: Option<impl Fn() -> T + Send + 'static>,
) -> Result<HotkeyId, HotkeyError>;
fn unregister(&mut self, id: HotkeyId) -> Result<(), HotkeyError>;
fn unregister_all(&mut self) -> Result<(), HotkeyError>;
fn handle_hotkey(&self) -> Option<T>;
fn event_loop(&self);
fn interrupt_handle(&self) -> InterruptHandle;
}
#[cfg(windows)]
pub struct InterruptHandle(HWND);
#[cfg(windows)]
unsafe impl Sync for InterruptHandle {}
#[cfg(windows)]
unsafe impl Send for InterruptHandle {}
#[cfg(windows)]
impl InterruptHandle {
pub fn interrupt(&self) {
unsafe {
PostMessageW(self.0, WM_NULL, 0, 0);
}
}
}
#[cfg(windows)]
pub fn get_global_keystate(vk: VirtualKey) -> bool {
use windows_sys::Win32::UI::Input::KeyboardAndMouse::GetAsyncKeyState;
let key_state = unsafe { GetAsyncKeyState(vk.to_vk_code() as i32) };
let key_state = key_state as u32 >> 31;
key_state == 1
}