From ee2b9f270ec0a07738d0380d7e2d4afb79cff306 Mon Sep 17 00:00:00 2001 From: Wind-Explorer Date: Wed, 7 Jan 2026 16:00:23 +0800 Subject: [PATCH] very wonky but works pet menu dismiss flow --- src-tauri/Cargo.lock | 133 +++++++++++++++++++++++++------ src-tauri/Cargo.toml | 1 + src-tauri/src/services/cursor.rs | 20 +++++ src-tauri/src/services/scene.rs | 38 +++++++-- src/routes/scene/+page.svelte | 7 +- 5 files changed, 167 insertions(+), 32 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index aa4f91d..09819b9 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -602,6 +602,19 @@ dependencies = [ "libc", ] +[[package]] +name = "core-graphics" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.10.1", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", +] + [[package]] name = "core-graphics-types" version = "0.2.0" @@ -967,6 +980,31 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" +[[package]] +name = "enigo" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71c6c56e50f7acae2906a0dcbb34529ca647e40421119ad5d12e7f8ba6e50010" +dependencies = [ + "core-foundation 0.10.1", + "core-graphics 0.25.0", + "foreign-types-shared 0.3.1", + "libc", + "log", + "nom", + "objc2 0.6.3", + "objc2-app-kit", + "objc2-foundation 0.3.2", + "tempfile", + "wayland-client", + "wayland-protocols-misc", + "wayland-protocols-wlr", + "windows 0.61.3", + "x11rb", + "xkbcommon", + "xkeysym", +] + [[package]] name = "enumflags2" version = "0.7.12" @@ -1141,6 +1179,7 @@ dependencies = [ "base64 0.22.1", "device_query", "dotenvy", + "enigo", "flate2", "gif", "image", @@ -2302,6 +2341,15 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +[[package]] +name = "memmap2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.9.1" @@ -2441,6 +2489,15 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -3066,7 +3123,7 @@ checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ "base64 0.22.1", "indexmap 2.12.0", - "quick-xml 0.38.4", + "quick-xml", "serde", "time", ] @@ -3204,15 +3261,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "quick-xml" -version = "0.37.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" -dependencies = [ - "memchr", -] - [[package]] name = "quick-xml" version = "0.38.4" @@ -4037,7 +4085,7 @@ checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" dependencies = [ "bytemuck", "cfg_aliases", - "core-graphics", + "core-graphics 0.24.0", "foreign-types 0.5.0", "js-sys", "log", @@ -4222,7 +4270,7 @@ dependencies = [ "bitflags 2.10.0", "block2 0.6.2", "core-foundation 0.10.1", - "core-graphics", + "core-graphics 0.24.0", "crossbeam-channel", "dispatch", "dlopen2", @@ -5385,9 +5433,9 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +checksum = "fee64194ccd96bf648f42a65a7e589547096dfa702f7cadef84347b66ad164f9" dependencies = [ "cc", "downcast-rs", @@ -5399,9 +5447,9 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.11" +version = "0.31.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +checksum = "b8e6faa537fbb6c186cb9f1d41f2f811a4120d1b57ec61f50da451a0c5122bec" dependencies = [ "bitflags 2.10.0", "rustix", @@ -5411,9 +5459,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.9" +version = "0.32.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +checksum = "baeda9ffbcfc8cd6ddaade385eaf2393bd2115a69523c735f12242353c3df4f3" dependencies = [ "bitflags 2.10.0", "wayland-backend", @@ -5422,21 +5470,47 @@ dependencies = [ ] [[package]] -name = "wayland-scanner" -version = "0.31.7" +name = "wayland-protocols-misc" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +checksum = "791c58fdeec5406aa37169dd815327d1e47f334219b523444bc26d70ceb4c34e" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" dependencies = [ "proc-macro2", - "quick-xml 0.37.5", + "quick-xml", "quote", ] [[package]] name = "wayland-sys" -version = "0.31.7" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" dependencies = [ "dlib", "log", @@ -6206,6 +6280,17 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" +[[package]] +name = "xkbcommon" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a974f48060a14e95705c01f24ad9c3345022f4d97441b8a36beb7ed5c4a02d" +dependencies = [ + "libc", + "memmap2", + "xkeysym", +] + [[package]] name = "xkeysym" version = "0.2.1" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4b15fa5..46c75e0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -47,6 +47,7 @@ tauri-plugin-dialog = "2.4.2" image = {version = "0.25.9", default-features = false, features = ["gif"] } gif = "0.14.1" raw-window-handle = "0.6" +enigo = { version = "0.6.1", features = ["wayland"] } [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] tauri-plugin-global-shortcut = "2" diff --git a/src-tauri/src/services/cursor.rs b/src-tauri/src/services/cursor.rs index 310d45d..1f06239 100644 --- a/src-tauri/src/services/cursor.rs +++ b/src-tauri/src/services/cursor.rs @@ -1,6 +1,7 @@ use device_query::{DeviceEvents, DeviceEventsHandler}; use once_cell::sync::OnceCell; use serde::{Deserialize, Serialize}; +use std::sync::{Arc, Mutex}; use std::time::Duration; use tauri::Emitter; use tokio::sync::mpsc; @@ -26,6 +27,15 @@ pub struct CursorPositions { } static CURSOR_TRACKER: OnceCell<()> = OnceCell::new(); +static LATEST_CURSOR_POSITION: OnceCell>>> = OnceCell::new(); + +/// Get the latest known cursor position (thread-safe) +pub fn get_latest_cursor_position() -> Option { + LATEST_CURSOR_POSITION + .get() + .and_then(|mutex| mutex.lock().ok()) + .and_then(|guard| guard.clone()) +} /// Convert absolute screen coordinates to normalized coordinates (0.0 - 1.0) pub fn absolute_to_normalized(pos: &CursorPosition) -> CursorPosition { @@ -59,6 +69,9 @@ pub async fn start_cursor_tracking() -> Result<(), String> { // Use OnceCell to ensure this only runs once, even if called from multiple windows CURSOR_TRACKER.get_or_init(|| { + // Initialize the shared state + LATEST_CURSOR_POSITION.get_or_init(|| Arc::new(Mutex::new(None))); + info!("First call to start_cursor_tracking - spawning cursor tracking task"); tauri::async_runtime::spawn(async { if let Err(e) = init_cursor_tracking().await { @@ -134,6 +147,13 @@ async fn init_cursor_tracking() -> Result<(), String> { y: position.1 as f64, }; + // Update global state + if let Some(mutex) = LATEST_CURSOR_POSITION.get() { + if let Ok(mut guard) = mutex.lock() { + *guard = Some(raw.clone()); + } + } + let mapped = absolute_to_normalized(&raw); let positions = CursorPositions { raw, mapped }; diff --git a/src-tauri/src/services/scene.rs b/src-tauri/src/services/scene.rs index 71649bf..32e4635 100644 --- a/src-tauri/src/services/scene.rs +++ b/src-tauri/src/services/scene.rs @@ -32,7 +32,7 @@ fn scene_interactive_state() -> Arc { .clone() } -pub fn update_scene_interactive(interactive: bool) { +pub fn update_scene_interactive(interactive: bool, should_click: bool) { let app_handle = get_app_handle(); // If we are forcing interactive to false (e.g. background click), clear any open menus @@ -48,6 +48,27 @@ pub fn update_scene_interactive(interactive: bool) { error!("Failed to toggle scene cursor events: {}", e); } + if should_click { + // Get cursor position on screen and use Enigo to click + if let Some(pos) = crate::services::cursor::get_latest_cursor_position() { + use enigo::{Button, Direction, Enigo, Mouse, Settings}; + // Initialize Enigo with default settings, handling potential failure + match Enigo::new(&Settings::default()) { + Ok(mut enigo) => { + // Perform a click (Press and Release) + // We ignore the result of the click action itself for now as it usually succeeds if init did + let _ = enigo.button(Button::Left, Direction::Click); + info!("Simulated click at ({}, {})", pos.x, pos.y); + } + Err(e) => { + error!("Failed to initialize Enigo for clicking: {}", e); + } + } + } else { + warn!("Cannot click: No cursor position available yet"); + } + } + if let Err(e) = window.emit("scene-interactive", &interactive) { error!("Failed to emit scene interactive event: {}", e); } @@ -57,8 +78,8 @@ pub fn update_scene_interactive(interactive: bool) { } #[tauri::command] -pub fn set_scene_interactive(interactive: bool) { - update_scene_interactive(interactive); +pub fn set_scene_interactive(interactive: bool, should_click: bool) { + update_scene_interactive(interactive, should_click); } #[tauri::command] @@ -68,6 +89,11 @@ pub fn set_pet_menu_state(id: String, open: bool) { if let Ok(mut menus) = menus_arc.lock() { if open { menus.insert(id); + get_app_handle() + .get_window(SCENE_WINDOW_LABEL) + .expect("Scene window should be present") + .set_focus() + .expect("Scene window should be focused"); } else { menus.remove(&id); } @@ -84,7 +110,7 @@ pub fn set_pet_menu_state(id: String, open: bool) { // For now, let the loop handle it to avoid race conditions with key states. // But if we just OPENED a menu, we definitely want to ensure interactive is TRUE. if should_update { - update_scene_interactive(true); + update_scene_interactive(true, false); } } @@ -97,7 +123,7 @@ extern "C" { fn start_scene_modifier_listener() { MODIFIER_LISTENER_INIT.get_or_init(|| { let state = scene_interactive_state(); - update_scene_interactive(false); + update_scene_interactive(false, false); let app_handle = get_app_handle().clone(); @@ -159,7 +185,7 @@ fn start_scene_modifier_listener() { info!("Interactive state changed to: {}", interactive); let previous = state.swap(interactive, Ordering::SeqCst); if previous != interactive { - update_scene_interactive(interactive); + update_scene_interactive(interactive, false); } last_interactive = interactive; } diff --git a/src/routes/scene/+page.svelte b/src/routes/scene/+page.svelte index 4934457..a2c406f 100644 --- a/src/routes/scene/+page.svelte +++ b/src/routes/scene/+page.svelte @@ -37,8 +37,11 @@