use crate::compat::OnceLock;
use crate::core::ObjectId;
use crate::platform::windows::types::{WindowsHandleKind, WindowsPlatform};
use crate::platform::WidgetTriggerEvent;
use crate::platform::WidgetTriggerKind;
#[cfg(target_os = "windows")]
pub(crate) fn ensure_window_class_registered() {
unsafe extern "system" {
fn GetModuleHandleW(lpModuleName: *const u16) -> *mut std::ffi::c_void;
}
static REGISTERED: OnceLock<()> = OnceLock::new();
REGISTERED.get_or_init(|| unsafe {
use std::ptr::null_mut;
use winapi::um::winuser::{
LoadCursorW, RegisterClassW, CS_HREDRAW, CS_VREDRAW, IDC_ARROW, WNDCLASSW,
};
let class_name = WindowsPlatform::to_wide("RustWidgetsWindowClass");
let hinstance = GetModuleHandleW(std::ptr::null());
let mut wnd_class: WNDCLASSW = std::mem::zeroed();
wnd_class.style = CS_HREDRAW | CS_VREDRAW;
wnd_class.lpfnWndProc = Some(super::types::rw_wnd_proc);
wnd_class.hInstance = hinstance as _;
wnd_class.hCursor = LoadCursorW(null_mut(), IDC_ARROW);
wnd_class.lpszClassName = class_name.as_ptr();
if RegisterClassW(&wnd_class) == 0 {
log::error!("[windows] RegisterClassW failed — window class not registered");
}
});
}
#[cfg(target_os = "windows")]
static ACTIVE_WINDOWS_PLATFORM: OnceLock<usize> = OnceLock::new();
#[cfg(target_os = "windows")]
pub(crate) fn active_windows_platform() -> Option<&'static WindowsPlatform> {
let ptr = *ACTIVE_WINDOWS_PLATFORM.get()? as *const WindowsPlatform;
if ptr.is_null() {
None
} else {
Some(unsafe { &*ptr })
}
}
#[cfg(target_os = "windows")]
pub(crate) fn register_active_platform(platform: &'static WindowsPlatform) {
if let Err(prev) = ACTIVE_WINDOWS_PLATFORM.set(platform as *const WindowsPlatform as usize) {
log::error!("[windows] register_active_platform already set — ignoring duplicate");
let _ = prev;
}
}
#[cfg(target_os = "windows")]
pub(crate) fn control_notify_kind_for_widget(
kind: WindowsHandleKind,
notify_code: u32,
) -> Option<WidgetTriggerKind> {
crate::platform::windows_notify::control_notify_kind_for_widget(kind, notify_code)
}
#[cfg(target_os = "windows")]
pub(crate) fn enqueue_control_notify_event(
platform: &WindowsPlatform,
widget_id: ObjectId,
notify_code: u32,
) -> bool {
let widget_kind = match platform.state.kind_of(widget_id) {
Some(kind) => kind,
None => return false,
};
let kind = match control_notify_kind_for_widget(widget_kind, notify_code) {
Some(kind) => kind,
None => return false,
};
if let Ok(mut events) = platform.menu_state.pending_widget_events.lock() {
events.push_back(WidgetTriggerEvent { widget_id, kind });
if crate::platform::windows_notify::combo_selchange_is_dual_emitted(widget_kind, kind) {
events
.push_back(WidgetTriggerEvent { widget_id, kind: WidgetTriggerKind::ValueChanged });
}
return true;
}
false
}
#[cfg(target_os = "windows")]
pub(crate) fn notify_kind_for_widget(
kind: WindowsHandleKind,
notify_code: u32,
) -> Option<WidgetTriggerKind> {
crate::platform::windows_notify::notify_kind_for_widget(kind, notify_code)
}