From 1545556d703fc7f1e1d7f4c3204806b6d9bc6417 Mon Sep 17 00:00:00 2001 From: TheRedDeveloper Date: Tue, 17 Feb 2026 22:20:36 +0100 Subject: [PATCH 1/3] expose HWND via window::windows_hwnd() --- src/lib.rs | 9 +++++++++ src/native/windows.rs | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index e7f9d500..a8ab98ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -439,6 +439,15 @@ pub mod window { let d = native_display().lock().unwrap(); d.view_ctrl } + + /// Get the main window HWND as a raw pointer (`*mut c_void`). + /// + /// Returns `null_mut()` if the window has not been created yet. + /// Only available on Windows. + #[cfg(target_os = "windows")] + pub fn windows_hwnd() -> *mut std::ffi::c_void { + crate::native::windows::get_window_hwnd() + } } #[derive(Debug, Copy, Clone, PartialEq, Hash, Eq)] diff --git a/src/native/windows.rs b/src/native/windows.rs index 01ffe5fa..c7c1b8cf 100644 --- a/src/native/windows.rs +++ b/src/native/windows.rs @@ -44,9 +44,19 @@ const WM_KILLFOCUS: UINT = 0x0008; /// Global flag tracking whether IME has been explicitly disabled by the user. /// This is controlled via `show_keyboard(bool)` API calls. -use std::sync::atomic::AtomicBool; +use std::sync::atomic::{AtomicBool, AtomicPtr}; static IME_USER_DISABLED: AtomicBool = AtomicBool::new(false); +/// The main window HWND, stored as a raw pointer for cross-crate access. +static WINDOW_HWND: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + +/// Get the main window HWND as a raw pointer. +/// +/// Returns `null_mut()` if the window has not been created yet. +pub fn get_window_hwnd() -> *mut std::ffi::c_void { + WINDOW_HWND.load(std::sync::atomic::Ordering::Acquire) +} + // IME composition form constants const CFS_POINT: DWORD = 0x0002; const CFS_CANDIDATEPOS: DWORD = 0x0040; @@ -964,6 +974,9 @@ unsafe fn create_window( ); assert!(!hwnd.is_null()); + // Store the HWND globally so external code can access it + WINDOW_HWND.store(hwnd as *mut std::ffi::c_void, std::sync::atomic::Ordering::Release); + // NOTE: Do not call ShowWindow here! // Must show window AFTER SetPixelFormat and wglCreateContext // Otherwise IME will not work correctly. From 1ebbd8a4dfe450101d84bc570d7ef4a5d61ada5c Mon Sep 17 00:00:00 2001 From: TheRedDeveloper Date: Wed, 18 Feb 2026 17:02:40 +0100 Subject: [PATCH 2/3] Store HWND in NativeDisplayData, make get_window_hwnd pub(crate) --- src/native.rs | 9 +++++++-- src/native/windows.rs | 15 ++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/native.rs b/src/native.rs index f3820036..089ce5c8 100644 --- a/src/native.rs +++ b/src/native.rs @@ -24,6 +24,9 @@ pub(crate) struct NativeDisplayData { pub dropped_files: DroppedFiles, pub blocking_event_loop: bool, + #[cfg(target_os = "windows")] + pub hwnd: *mut std::ffi::c_void, + #[cfg(target_vendor = "apple")] pub view: crate::native::apple::frameworks::ObjcId, #[cfg(target_os = "ios")] @@ -31,9 +34,9 @@ pub(crate) struct NativeDisplayData { #[cfg(target_vendor = "apple")] pub gfx_api: crate::conf::AppleGfxApi, } -#[cfg(target_vendor = "apple")] +#[cfg(any(target_vendor = "apple", target_os = "windows"))] unsafe impl Send for NativeDisplayData {} -#[cfg(target_vendor = "apple")] +#[cfg(any(target_vendor = "apple", target_os = "windows"))] unsafe impl Sync for NativeDisplayData {} impl NativeDisplayData { @@ -56,6 +59,8 @@ impl NativeDisplayData { clipboard, dropped_files: Default::default(), blocking_event_loop: false, + #[cfg(target_os = "windows")] + hwnd: std::ptr::null_mut(), #[cfg(target_vendor = "apple")] gfx_api: crate::conf::AppleGfxApi::OpenGl, #[cfg(target_vendor = "apple")] diff --git a/src/native/windows.rs b/src/native/windows.rs index c7c1b8cf..371c3dab 100644 --- a/src/native/windows.rs +++ b/src/native/windows.rs @@ -44,17 +44,14 @@ const WM_KILLFOCUS: UINT = 0x0008; /// Global flag tracking whether IME has been explicitly disabled by the user. /// This is controlled via `show_keyboard(bool)` API calls. -use std::sync::atomic::{AtomicBool, AtomicPtr}; +use std::sync::atomic::AtomicBool; static IME_USER_DISABLED: AtomicBool = AtomicBool::new(false); -/// The main window HWND, stored as a raw pointer for cross-crate access. -static WINDOW_HWND: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); - /// Get the main window HWND as a raw pointer. /// /// Returns `null_mut()` if the window has not been created yet. -pub fn get_window_hwnd() -> *mut std::ffi::c_void { - WINDOW_HWND.load(std::sync::atomic::Ordering::Acquire) +pub(crate) fn get_window_hwnd() -> *mut std::ffi::c_void { + crate::native_display().lock().unwrap().hwnd } // IME composition form constants @@ -974,9 +971,6 @@ unsafe fn create_window( ); assert!(!hwnd.is_null()); - // Store the HWND globally so external code can access it - WINDOW_HWND.store(hwnd as *mut std::ffi::c_void, std::sync::atomic::Ordering::Release); - // NOTE: Do not call ShowWindow here! // Must show window AFTER SetPixelFormat and wglCreateContext // Otherwise IME will not work correctly. @@ -1219,6 +1213,9 @@ where ..NativeDisplayData::new(conf.window_width, conf.window_height, tx, clipboard) }); + // Store the HWND in NativeDisplayData so external code can access it via window::windows_hwnd() + crate::native_display().lock().unwrap().hwnd = wnd as *mut std::ffi::c_void; + display.update_dimensions(wnd); let mut wgl = wgl::Wgl::new(&mut display); From 2b90706d9ba9e69a09009709e7ca3940a5f9a906 Mon Sep 17 00:00:00 2001 From: TheRedDeveloper Date: Wed, 18 Feb 2026 18:06:33 +0100 Subject: [PATCH 3/3] pass HWND in set_display, remove get_window_hwnd --- src/lib.rs | 2 +- src/native/windows.rs | 11 +---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a8ab98ce..ba32be01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -446,7 +446,7 @@ pub mod window { /// Only available on Windows. #[cfg(target_os = "windows")] pub fn windows_hwnd() -> *mut std::ffi::c_void { - crate::native::windows::get_window_hwnd() + crate::native_display().lock().unwrap().hwnd } } diff --git a/src/native/windows.rs b/src/native/windows.rs index 371c3dab..cf46ed3a 100644 --- a/src/native/windows.rs +++ b/src/native/windows.rs @@ -47,13 +47,6 @@ const WM_KILLFOCUS: UINT = 0x0008; use std::sync::atomic::AtomicBool; static IME_USER_DISABLED: AtomicBool = AtomicBool::new(false); -/// Get the main window HWND as a raw pointer. -/// -/// Returns `null_mut()` if the window has not been created yet. -pub(crate) fn get_window_hwnd() -> *mut std::ffi::c_void { - crate::native_display().lock().unwrap().hwnd -} - // IME composition form constants const CFS_POINT: DWORD = 0x0002; const CFS_CANDIDATEPOS: DWORD = 0x0040; @@ -1210,12 +1203,10 @@ where high_dpi: conf.high_dpi, dpi_scale: display.window_scale, blocking_event_loop: conf.platform.blocking_event_loop, + hwnd: wnd as *mut std::ffi::c_void, ..NativeDisplayData::new(conf.window_width, conf.window_height, tx, clipboard) }); - // Store the HWND in NativeDisplayData so external code can access it via window::windows_hwnd() - crate::native_display().lock().unwrap().hwnd = wnd as *mut std::ffi::c_void; - display.update_dimensions(wnd); let mut wgl = wgl::Wgl::new(&mut display);