use super::*;
use std::ptr::NonNull;
use std::rc::Rc;
use windows_sys::Win32::Foundation::{HWND, LPARAM, LRESULT, WPARAM};
use windows_sys::Win32::UI::WindowsAndMessaging::*;
pub unsafe extern "system" fn wnd_proc<W: WindowImpl>(
window: HWND, message_code: u32, w_param: WPARAM, l_param: LPARAM,
) -> LRESULT {
let handle_default = || unsafe { DefWindowProcW(window, message_code, w_param, l_param) };
let window = unsafe { HWnd::from_raw(window) };
match message_code {
WM_CREATE => {
let create = unsafe { &*(l_param as *const CREATESTRUCTW) };
let inner_ptr = create.lpCreateParams as *mut WindowData<W>;
let Some(inner_ptr) = NonNull::new(inner_ptr) else {
return -1;
};
if let Err(_e) = window.set_userdata_ptr(inner_ptr.as_ptr()) {
drop(Rc::from_raw(inner_ptr.as_ptr()));
return -1;
}
let result = {
let inner = unsafe { inner_ptr.as_ref() };
inner.initialize(window)
};
match result {
Ok(()) => 0,
Err(_) => {
let _ = window.set_userdata_ptr(core::ptr::null::<W>());
drop(Rc::from_raw(inner_ptr.as_ptr()));
-1
}
}
}
WM_DESTROY => {
let Some(state_ptr) = window.get_userdata_ptr::<WindowData<W>>() else {
return handle_default();
};
let state = unsafe { Rc::from_raw(state_ptr.as_ptr()) };
state.destroy_started(window);
let _ = window.set_userdata_ptr(core::ptr::null::<W>());
drop(state);
0
}
_ => {
let Some(inner_ptr) = window.get_userdata_ptr::<WindowData<W>>() else {
return handle_default();
};
let inner = unsafe { WindowData::from_raw(inner_ptr) };
let result = inner.handle_message(window, message_code, w_param, l_param);
drop(inner);
result.unwrap_or_else(handle_default)
}
}
}