From f9d20d8585da6eeeaa951be0acb9712ead5e754c Mon Sep 17 00:00:00 2001 From: EdisonJwa Date: Fri, 15 May 2026 22:08:02 +0800 Subject: [PATCH] fix(audio,windows): adapt Raw Input + hook backends to windows-rs 0.54 API shape Initial Task C commit (77c2a1d) used handle constructors and import paths that match windows-rs 0.58+, not the 0.54 version pinned via the workspace's transitive 'windows' dep. Compile errors on the Korean Windows 11 build: * HWND/HHOOK/HRAWINPUT take 'pub isize' in 0.54 (became raw pointers in 0.58). Use HWND(HWND_MESSAGE_PTR), HHOOK(0), HRAWINPUT(lparam.0) instead of *mut _ casts. * CreateWindowExW returns HWND directly in 0.54, not Result. Check hwnd.0 == 0 for null. * RegisterClassExW + WNDCLASSEXW are gated behind Win32_Graphics_Gdi in 0.54. Added that feature. * XBUTTON1 / XBUTTON2 live in Win32::UI::WindowsAndMessaging not Win32::UI::Input::KeyboardAndMouse in 0.54. * Win32_System_Threading needed for GetCurrentThreadId. * Unused Mutex import dropped. No behavioural change relative to 77c2a1d; just signature alignment. --- crates/chanora_audio/Cargo.toml | 2 + .../chanora_audio/src/ptt_backends/windows.rs | 67 +++++++++---------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/crates/chanora_audio/Cargo.toml b/crates/chanora_audio/Cargo.toml index 74537f4..9ed7e62 100644 --- a/crates/chanora_audio/Cargo.toml +++ b/crates/chanora_audio/Cargo.toml @@ -41,7 +41,9 @@ ndk-context = "0.1" # require a per-backend OS thread that owns a message pump. windows = { version = "0.54", features = [ "Win32_Foundation", + "Win32_Graphics_Gdi", "Win32_System_LibraryLoader", + "Win32_System_Threading", "Win32_UI_Input", "Win32_UI_Input_KeyboardAndMouse", "Win32_UI_WindowsAndMessaging", diff --git a/crates/chanora_audio/src/ptt_backends/windows.rs b/crates/chanora_audio/src/ptt_backends/windows.rs index dd566e4..80332d6 100644 --- a/crates/chanora_audio/src/ptt_backends/windows.rs +++ b/crates/chanora_audio/src/ptt_backends/windows.rs @@ -21,16 +21,13 @@ //! this file never tries. use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::thread; use tracing::{info, warn}; use windows::core::{w, PCWSTR}; use windows::Win32::Foundation::{HMODULE, HWND, LPARAM, LRESULT, WPARAM}; use windows::Win32::System::LibraryLoader::GetModuleHandleW; -use windows::Win32::UI::Input::KeyboardAndMouse::{ - XBUTTON1, XBUTTON2, -}; use windows::Win32::UI::Input::{ GetRawInputData, RegisterRawInputDevices, HRAWINPUT, RAWINPUT, RAWINPUTDEVICE, RAWINPUTHEADER, RID_INPUT, RIDEV_INPUTSINK, RIDEV_REMOVE, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE, @@ -40,7 +37,8 @@ use windows::Win32::UI::WindowsAndMessaging::{ PostThreadMessageW, RegisterClassExW, SetWindowsHookExW, TranslateMessage, UnhookWindowsHookEx, HC_ACTION, HHOOK, HOOKPROC, KBDLLHOOKSTRUCT, MSG, MSLLHOOKSTRUCT, WH_KEYBOARD_LL, WH_MOUSE_LL, WINDOW_EX_STYLE, WINDOW_STYLE, WM_INPUT, WM_KEYDOWN, WM_KEYUP, - WM_QUIT, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSEXW, + WM_QUIT, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSEXW, XBUTTON1, + XBUTTON2, }; use super::{AudioTransmitGate, DesktopPttBackend, PttBackendError, PttBinding}; @@ -392,30 +390,29 @@ unsafe fn run_raw_input_loop() -> bool { // class. let _atom = RegisterClassExW(&wc); - let hwnd = match CreateWindowExW( - WINDOW_EX_STYLE(0), - class_name, - PCWSTR::null(), - WINDOW_STYLE(0), - 0, - 0, - 0, - 0, - HWND(HWND_MESSAGE_PTR as *mut _), - None, - h_instance, - None, - ) { - Ok(h) => h, - Err(e) => { - warn!( - target: "chanora_audio", - error = %e, - "windows ptt: CreateWindowExW(HWND_MESSAGE) failed" - ); - return false; - } + let hwnd = unsafe { + CreateWindowExW( + WINDOW_EX_STYLE(0), + class_name, + PCWSTR::null(), + WINDOW_STYLE(0), + 0, + 0, + 0, + 0, + HWND(HWND_MESSAGE_PTR), + None, + h_instance, + None, + ) }; + if hwnd.0 == 0 { + warn!( + target: "chanora_audio", + "windows ptt: CreateWindowExW(HWND_MESSAGE) returned null" + ); + return false; + } // Register both keyboard and mouse, both with INPUTSINK so we // receive events even when unfocused. @@ -475,13 +472,13 @@ unsafe fn run_raw_input_loop() -> bool { usUsagePage: 0x01, usUsage: 0x06, dwFlags: RIDEV_REMOVE, - hwndTarget: HWND(std::ptr::null_mut()), + hwndTarget: HWND(0), }, RAWINPUTDEVICE { usUsagePage: 0x01, usUsage: 0x02, dwFlags: RIDEV_REMOVE, - hwndTarget: HWND(std::ptr::null_mut()), + hwndTarget: HWND(0), }, ]; let _ = RegisterRawInputDevices(&undo, std::mem::size_of::() as u32); @@ -502,7 +499,7 @@ unsafe extern "system" fn raw_input_wnd_proc( } unsafe fn handle_wm_input(lparam: LPARAM) { - let h_raw = HRAWINPUT(lparam.0 as *mut _); + let h_raw = HRAWINPUT(lparam.0); let mut size: u32 = 0; let header_sz = std::mem::size_of::() as u32; // First call: query buffer size. @@ -838,7 +835,7 @@ unsafe extern "system" fn kbd_hook_proc(code: i32, wparam: WPARAM, lparam: LPARA } }); } - CallNextHookEx(HHOOK(std::ptr::null_mut()), code, wparam, lparam) + CallNextHookEx(HHOOK(0), code, wparam, lparam) } unsafe extern "system" fn mouse_hook_proc(code: i32, wparam: WPARAM, lparam: LPARAM) -> LRESULT { @@ -853,9 +850,9 @@ unsafe extern "system" fn mouse_hook_proc(code: i32, wparam: WPARAM, lparam: LPA let xbutton = (m.mouseData >> 16) as u16; let want = ctx.binding.mouse_btn(); let want_xbutton = if want == 4 { - XBUTTON1.0 + XBUTTON1 } else if want == 5 { - XBUTTON2.0 + XBUTTON2 } else { 0 }; @@ -870,5 +867,5 @@ unsafe extern "system" fn mouse_hook_proc(code: i32, wparam: WPARAM, lparam: LPA } }); } - CallNextHookEx(HHOOK(std::ptr::null_mut()), code, wparam, lparam) + CallNextHookEx(HHOOK(0), code, wparam, lparam) }