mod event;
mod global;
pub mod message_loop;
mod types;
pub mod window;
use core::sync::atomic::{AtomicBool, Ordering};
use std::sync::LazyLock;
use anyhow::Context;
use asdf_overlay_window_event::Event;
use windows::Win32::UI::WindowsAndMessaging::HCURSOR;
use crate::{
event::EventSink, global::GlobalState, message_loop::MessageLoopState, window::WindowProcState,
};
static GLOBAL: LazyLock<GlobalState> = LazyLock::new(GlobalState::new);
pub struct Backends {}
impl Backends {
pub fn new<F>(f: F) -> anyhow::Result<Self>
where
F: Fn(Event) + Send + Sync + 'static,
{
static INITIALIZED: AtomicBool = AtomicBool::new(false);
if INITIALIZED.swap(true, Ordering::SeqCst) {
panic!("GlobalInputManager can only be initialized once");
}
EventSink::set(f);
asdf_overlay_hook::with_transaction(|| {
global::hook::install().context("global win32 functions")?;
message_loop::hook::install().context("win32 message loop functions")?;
Ok::<_, anyhow::Error>(())
})
.context("hook failed")?;
Ok(Self {})
}
pub fn windows(&self) -> impl Iterator<Item = u32> + '_ {
Self::get().windows.iter().map(|r| *r.key())
}
pub fn window<R>(&self, id: u32, f: impl FnOnce(&WindowProcState) -> R) -> Option<R> {
Self::get().windows.view(&id, |_, state| f(state))
}
pub fn message_loops(&self) -> impl Iterator<Item = u32> + '_ {
Self::get().message_loops.iter().map(|r| *r.key())
}
pub fn message_loop<R>(&self, id: u32, f: impl FnOnce(&MessageLoopState) -> R) -> Option<R> {
Self::get().message_loops.view(&id, |_, state| f(state))
}
#[inline]
pub fn input_blocked() -> bool {
Self::get().input_blocked()
}
#[inline]
pub fn block_input(&self) {
Self::get().block_input();
}
#[inline]
pub fn unblock_input(&self) {
Self::get().unblock_input();
}
#[inline]
pub fn set_blocking_cursor(&self, cursor: Option<HCURSOR>) {
Self::get().set_blocking_cursor(cursor);
}
pub fn reset(&self) {
Self::get().reset();
}
#[inline(always)]
fn get() -> &'static GlobalState {
&GLOBAL
}
}
impl Drop for Backends {
fn drop(&mut self) {
Self::get().unblock_input();
EventSink::clear();
}
}