diff --git a/Cargo.lock b/Cargo.lock index 6292e96..027bc20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -425,6 +425,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.11.1" @@ -1899,7 +1905,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core 0.61.2", ] [[package]] @@ -2030,6 +2036,19 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png 0.18.1", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -2398,6 +2417,16 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + [[package]] name = "muda" version = "0.19.2" @@ -3102,6 +3131,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pxfm" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" + [[package]] name = "quick-xml" version = "0.39.4" @@ -5567,19 +5602,6 @@ dependencies = [ "windows-strings 0.4.2", ] -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement 0.60.2", - "windows-interface 0.59.3", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", -] - [[package]] name = "windows-future" version = "0.2.1" @@ -5675,15 +5697,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows-strings" version = "0.1.0" @@ -5703,15 +5716,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -6055,6 +6059,7 @@ dependencies = [ "ed25519-dalek", "futures-util", "getrandom 0.4.3", + "image", "lazy_static", "objc2", "objc2-app-kit", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1b0ae7f..1a78d07 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -41,7 +41,18 @@ wyd-common = { path = "../src-common" } tokio = { version = "1.53.1", features = ["macros", "rt-multi-thread"] } [target.'cfg(target_os = "windows")'.dependencies] -windows = "0.58" +image = { version = "0.25", default-features = false, features = ["png"] } +windows = { version = "0.58", features = [ + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Gdi", + "Win32_Storage_FileSystem", + "Win32_System_ProcessStatus", + "Win32_System_Threading", + "Win32_UI_Accessibility", + "Win32_UI_Shell", + "Win32_UI_WindowsAndMessaging", +] } [target.'cfg(target_os = "macos")'.dependencies] objc2 = "0.6.3" diff --git a/src-tauri/src/cursor/mod.rs b/src-tauri/src/cursor/mod.rs index b354a31..87e20ab 100644 --- a/src-tauri/src/cursor/mod.rs +++ b/src-tauri/src/cursor/mod.rs @@ -184,24 +184,18 @@ async fn init_cursor_tracking_i( println!("Device event handler created successfully"); println!("Setting up mouse move handler for event broadcasting..."); - // #[cfg(target_os = "windows")] + #[cfg(not(target_os = "windows"))] let scale_factor = monitor.scale_factor(); // The producer closure moves `tx` into it. // device_query runs this closure on its own thread. let _guard = device_state.on_mouse_move(move |position: &(i32, i32)| { - // `device_query` crate appears to behave - // differently on Windows vs other platforms. - // - // It doesn't take into account the monitor scale - // factor on Windows, so we handle it manually. #[cfg(target_os = "windows")] let raw = CursorPosition { - x: position.0 as f64 / scale_factor, - y: position.1 as f64 / scale_factor, + x: position.0 as f64, + y: position.1 as f64, }; - // NOTE: Inclusion of scale factor was not necessary in the past, but now required. Confirm behaviours. #[cfg(not(target_os = "windows"))] let raw = CursorPosition { x: position.0 as f64 * scale_factor, diff --git a/src-tauri/src/ufa/windows.rs b/src-tauri/src/ufa/windows.rs index 9939dd4..4398e00 100644 --- a/src-tauri/src/ufa/windows.rs +++ b/src-tauri/src/ufa/windows.rs @@ -1,10 +1,9 @@ -use super::types::AppMetadata; +use super::types::AppMeta; use std::ffi::OsString; use std::iter; use std::os::windows::ffi::OsStringExt; use std::path::Path; use std::ptr; -use tracing::{info, warn}; use windows::core::PCWSTR; use windows::Win32::Foundation::HWND; use windows::Win32::Globalization::GetUserDefaultLangID; @@ -18,7 +17,7 @@ use windows::Win32::UI::WindowsAndMessaging::{ pub fn listen_for_active_app_changes(callback: F) where - F: Fn(AppMetadata) + Send + 'static, + F: Fn(AppMeta) + Send + 'static, { // Run the hook on a background thread so we don't block the caller. std::thread::spawn(move || unsafe { @@ -52,7 +51,7 @@ where // RefCell is safe here because the callback is stored and accessed only within the dedicated event loop thread. // No concurrent access occurs since WinEventHook runs on a single background thread. thread_local! { - static CALLBACK: std::cell::RefCell>> = + static CALLBACK: std::cell::RefCell>> = std::cell::RefCell::new(None); } @@ -76,35 +75,35 @@ unsafe extern "system" fn win_event_proc( } /// Retrieves metadata for the active application on Windows, optionally using a provided window handle. -pub fn get_active_app_metadata_windows(hwnd_override: Option) -> AppMetadata { +pub fn get_active_app_metadata_windows(hwnd_override: Option) -> AppMeta { unsafe { let hwnd = hwnd_override.unwrap_or_else(|| GetForegroundWindow()); if hwnd.0 == std::ptr::null_mut() { - warn!("No foreground window found"); - return AppMetadata { - localized: None, - unlocalized: None, - app_icon_b64: None, + eprintln!("No foreground window found"); + return AppMeta { + local: None, + unlocal: None, + ico: None, }; } let mut pid: u32 = 0; GetWindowThreadProcessId(hwnd, Some(&mut pid)); if pid == 0 { - warn!("Failed to get process ID for foreground window"); - return AppMetadata { - localized: None, - unlocalized: None, - app_icon_b64: None, + eprintln!("Failed to get process ID for foreground window"); + return AppMeta { + local: None, + unlocal: None, + ico: None, }; } let process_handle = match OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid) { Ok(h) if !h.is_invalid() => h, _ => { - warn!("Failed to open process {} for querying", pid); - return AppMetadata { - localized: None, - unlocalized: None, - app_icon_b64: None, + eprintln!("Failed to open process {} for querying", pid); + return AppMeta { + local: None, + unlocal: None, + ico: None, }; } }; @@ -114,11 +113,11 @@ pub fn get_active_app_metadata_windows(hwnd_override: Option) -> AppMetada let exe_path = if size > 0 { OsString::from_wide(&buffer[..size as usize]) } else { - warn!("Failed to get module file name for process {}", pid); - return AppMetadata { - localized: None, - unlocalized: None, - app_icon_b64: None, + eprintln!("Failed to get module file name for process {}", pid); + return AppMeta { + local: None, + unlocal: None, + ico: None, }; }; let exe_path_str = exe_path.to_string_lossy(); @@ -143,10 +142,10 @@ pub fn get_active_app_metadata_windows(hwnd_override: Option) -> AppMetada let app_icon_b64 = get_active_app_icon_b64(&exe_path_str); - AppMetadata { - localized, - unlocalized, - app_icon_b64, + AppMeta { + local: localized, + unlocal: unlocalized, + ico: app_icon_b64, } } } @@ -281,7 +280,7 @@ struct IconHandle(windows::Win32::UI::WindowsAndMessaging::HICON); impl Drop for IconHandle { fn drop(&mut self) { unsafe { - windows::Win32::UI::WindowsAndMessaging::DestroyIcon(self.0); + let _ = windows::Win32::UI::WindowsAndMessaging::DestroyIcon(self.0); } } } @@ -316,7 +315,7 @@ fn get_active_app_icon_b64(exe_path: &str) -> Option { ); if result == 0 || file_info.hIcon.is_invalid() { - warn!("Failed to get icon for {}", exe_path); + eprintln!("Failed to get icon for {}", exe_path); return None; } @@ -325,7 +324,7 @@ fn get_active_app_icon_b64(exe_path: &str) -> Option { // Get icon info to extract bitmap let mut icon_info: ICONINFO = std::mem::zeroed(); if GetIconInfo(icon_handle.0, &mut icon_info).is_err() { - warn!("Failed to get icon info for {}", exe_path); + eprintln!("Failed to get icon info for {}", exe_path); return None; } @@ -339,13 +338,10 @@ fn get_active_app_icon_b64(exe_path: &str) -> Option { { let _ = DeleteObject(icon_info.hbmColor); let _ = DeleteObject(icon_info.hbmMask); - warn!("Failed to get bitmap object for {}", exe_path); + eprintln!("Failed to get bitmap object for {}", exe_path); return None; } - let width = bitmap.bmWidth; - let height = bitmap.bmHeight; - // Create device contexts let hdc_screen = windows::Win32::Graphics::Gdi::GetDC(HWND(ptr::null_mut())); let hdc_mem = CreateCompatibleDC(hdc_screen); @@ -402,7 +398,7 @@ fn get_active_app_icon_b64(exe_path: &str) -> Option { let _ = DeleteObject(icon_info.hbmMask); if result == 0 { - warn!("Failed to get bitmap bits for {}", exe_path); + eprintln!("Failed to get bitmap bits for {}", exe_path); return None; } @@ -419,7 +415,7 @@ fn get_active_app_icon_b64(exe_path: &str) -> Option { ) { Some(img) => img, None => { - warn!("Failed to create image from buffer for {}", exe_path); + eprintln!("Failed to create image from buffer for {}", exe_path); return None; } }; @@ -429,13 +425,13 @@ fn get_active_app_icon_b64(exe_path: &str) -> Option { &mut std::io::Cursor::new(&mut png_buffer), image::ImageFormat::Png, ) { - warn!("Failed to encode PNG for {}: {}", exe_path, e); + eprintln!("Failed to encode PNG for {}: {}", exe_path, e); return None; } let encoded = STANDARD.encode(&png_buffer); - info!( + println!( "App icon captured: {}, PNG bytes: {}, base64 size: {} bytes", exe_path, png_buffer.len(), @@ -443,7 +439,7 @@ fn get_active_app_icon_b64(exe_path: &str) -> Option { ); if encoded.len() > super::types::MAX_ICON_B64_SIZE { - warn!( + eprintln!( "Icon for {} exceeds size limit ({} > {} bytes), skipping", exe_path, encoded.len(),