use wasm_bindgen::JsCast;
use super::*;
#[cfg(feature = "binding")]
#[cfg(feature = "win-binding")]
::modwire::expose!(
pub win_binding
);
::modwire::expose!(
pub cursor_client_x
pub cursor_client_y
pub cursor_offset_x
pub cursor_offset_y
pub cursor_page_x
pub cursor_page_y
pub cursor_screen_x
pub cursor_screen_y
pub device
pub element_w
pub element_h
pub inner_h
pub inner_w
pub outer_h
pub outer_w
);
static MOUSE_EVENTS: [&str; 6] = [
"mousemove",
"mousedown",
"mouseup",
"click",
"dblclick",
"contextmenu"
];
pub type Result<T> = ::std::result::Result<T, Error>;
#[repr(u8)]
#[derive(Debug, Clone, PartialEq)]
pub enum Error {
PropertyAccessFailure(::wasm_bindgen::JsValue),
EventListenerAttachmentFailure(::wasm_bindgen::JsValue),
MissingWindow,
MissingDocument,
MissingDocumentElement,
UnsupportedConvertionToF64
}
type DropTokenSlot = Option<::std::rc::Rc<::std::cell::RefCell<Box<dyn FnMut() + 'static>>>>;
#[repr(transparent)]
pub struct DropToken(DropTokenSlot);
impl DropToken {
pub fn from_static_dyn_fn_mut_box(on_event: Box<dyn FnMut() + 'static>) -> Self {
Self({
let ret: ::std::cell::RefCell<_> = ::std::cell::RefCell::new(on_event);
let ret: ::std::rc::Rc<_> = ::std::rc::Rc::new(ret);
let ret: Option<_> = Some(ret);
ret
})
}
pub fn from_dyn_fn_mut_closure(on_event: ::wasm_bindgen::closure::Closure<dyn FnMut()>) -> Self {
Self({
let ret: ::std::cell::RefCell<_> = ::std::cell::RefCell::new(on_event);
let ret: ::std::rc::Rc<_> = ::std::rc::Rc::new(ret);
let ret: Box<dyn FnMut()> = Box::new({
let ptr: ::std::rc::Rc<_> = ret.to_owned();
move || {
let c: ::std::cell::RefMut<_> = ptr.borrow_mut();
let c: &::js_sys::Function = c.as_ref().unchecked_ref();
if c.call0(&::wasm_bindgen::JsValue::NULL).is_err() {
::web_sys::console::log_1(&r#"
[ALERT] Cleanup procedure aborted. Residual closure may persist in memory. Investigate reference counts and reentrancy conditions.
"#.into());
}
}
});
let ret: ::std::cell::RefCell<_> = ::std::cell::RefCell::new(ret);
let ret: ::std::rc::Rc<_> = ::std::rc::Rc::new(ret);
let ret: Option<_> = Some(ret);
ret
})
}
}
impl ToOwned for DropToken {
type Owned = Self;
fn to_owned(&self) -> Self::Owned {
if let Some(c) = &self.0 {
let c: ::std::rc::Rc<_> = c.to_owned();
Self(Some(c))
} else {
Self(None)
}
}
}
impl Drop for DropToken {
fn drop(&mut self) {
let Some(ref c) = self.0 else {
return
};
let Ok(mut c) = c.try_borrow_mut() else {
::web_sys::console::error_1(&"[FAULT]: Cleanup lock unavailable. Disposal skipped. Possible leak. Check for reentrancy.".into());
return
};
c();
}
}
fn on<A, B>(events: Vec<&'static str>, event_handler: A) -> Result<DropToken>
where
A: 'static,
A: FnMut(B),
B: 'static,
B: ::wasm_bindgen::convert::FromWasmAbi {
use ::wasm_bindgen::prelude::*;
use ::std::rc;
use ::std::cell;
let win: ::web_sys::Window = ::web_sys::window().ok_or(Error::MissingWindow)?;
let closure: rc::Rc<_> = {
let ret: Box<_> = Box::new(event_handler) as Box<dyn FnMut(_)>;
let ret: Closure<_> = Closure::wrap(ret);
let ret: Option<_> = Some(ret);
let ret: cell::RefCell<_> = cell::RefCell::new(ret);
let ret: rc::Rc<_> = rc::Rc::new(ret);
ret
};
{
let events: Vec<_> = events.to_owned();
let closure: cell::RefMut<_> = closure.borrow_mut();
let Some(closure) = closure.as_ref() else {
return Err(Error::EventListenerAttachmentFailure(JsValue::from("")))
};
let closure: &::js_sys::Function = closure.as_ref().unchecked_ref();
for event in events {
win.add_event_listener_with_callback(event, closure).map_err(Error::EventListenerAttachmentFailure)?;
}
};
Ok(DropToken::from_static_dyn_fn_mut_box(Box::new({
let closure: rc::Rc<_> = closure.to_owned();
let events: Vec<_> = events.to_owned();
move || {
let mut closure: cell::RefMut<_> = closure.borrow_mut();
{
let Some(closure) = closure.as_ref() else {
return
};
let closure: &::js_sys::Function = closure.as_ref().unchecked_ref();
for event in events.iter() {
win.remove_event_listener_with_callback(event, closure).expect("");
}
};
*closure = None;
}
})))
}