From 407c7d13c7e2d1105c840da143fd44981691ccb7 Mon Sep 17 00:00:00 2001 From: Wind-Explorer Date: Tue, 25 Nov 2025 12:06:01 +0800 Subject: [PATCH] cursor position on screen stream --- src-tauri/Cargo.lock | 130 +++++++++++++++++++++++++++---- src-tauri/Cargo.toml | 2 + src-tauri/src/lib.rs | 5 +- src-tauri/src/services/cursor.rs | 31 ++++++++ src-tauri/src/services/mod.rs | 1 + src/channels/cursor.ts | 12 +++ src/routes/+layout.ts | 3 + src/routes/scene/+page.svelte | 23 ++++-- 8 files changed, 185 insertions(+), 22 deletions(-) create mode 100644 src-tauri/src/services/cursor.rs create mode 100644 src/channels/cursor.ts diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index bf15737..495adb2 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -679,6 +679,20 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "device_query" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7331225604b9b097b41872d550134933d4be83465d70a2c4a132b929f99aaca" +dependencies = [ + "macos-accessibility-client", + "pkg-config", + "readkey", + "readmouse", + "windows 0.48.0", + "x11", +] + [[package]] name = "digest" version = "0.10.7" @@ -707,7 +721,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -876,7 +890,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1002,6 +1016,8 @@ dependencies = [ name = "friendolls-desktop" version = "0.1.0" dependencies = [ + "device_query", + "once_cell", "reqwest", "serde", "serde_json", @@ -2028,6 +2044,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +[[package]] +name = "macos-accessibility-client" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf7710fbff50c24124331760978fb9086d6de6288dcdb38b25a97f8b1bdebbb" +dependencies = [ + "core-foundation 0.9.4", + "core-foundation-sys", +] + [[package]] name = "markup5ever" version = "0.14.1" @@ -3050,6 +3076,18 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "readkey" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a36870cefdfcff57edbc0fa62165f42dfd4e5a0d8965117c1ea84c5700e4450" + +[[package]] +name = "readmouse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be105c72a1e6a5a1198acee3d5b506a15676b74a02ecd78060042a447f408d94" + [[package]] name = "redox_syscall" version = "0.5.18" @@ -3195,7 +3233,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3823,7 +3861,7 @@ dependencies = [ "tao-macros", "unicode-segmentation", "url", - "windows", + "windows 0.61.3", "windows-core", "windows-version", "x11-dl", @@ -3894,7 +3932,7 @@ dependencies = [ "webkit2gtk", "webview2-com", "window-vibrancy", - "windows", + "windows 0.61.3", ] [[package]] @@ -4010,7 +4048,7 @@ dependencies = [ "tauri-plugin", "thiserror 2.0.17", "url", - "windows", + "windows 0.61.3", "zbus", ] @@ -4051,7 +4089,7 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows", + "windows 0.61.3", ] [[package]] @@ -4077,7 +4115,7 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows", + "windows 0.61.3", "wry", ] @@ -4140,7 +4178,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4878,7 +4916,7 @@ checksum = "d4ba622a989277ef3886dd5afb3e280e3dd6d974b766118950a08f8f678ad6a4" dependencies = [ "webview2-com-macros", "webview2-com-sys", - "windows", + "windows 0.61.3", "windows-core", "windows-implement", "windows-interface", @@ -4902,7 +4940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c" dependencies = [ "thiserror 2.0.17", - "windows", + "windows 0.61.3", "windows-core", ] @@ -4928,7 +4966,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4952,6 +4990,15 @@ dependencies = [ "windows-version", ] +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows" version = "0.61.3" @@ -5131,6 +5178,21 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -5188,6 +5250,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -5206,6 +5274,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -5224,6 +5298,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -5254,6 +5334,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -5272,6 +5358,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -5290,6 +5382,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -5308,6 +5406,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -5399,7 +5503,7 @@ dependencies = [ "webkit2gtk", "webkit2gtk-sys", "webview2-com", - "windows", + "windows 0.61.3", "windows-core", "windows-version", "x11-dl", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 384d0fa..91d0187 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -27,6 +27,8 @@ tauri-plugin-global-shortcut = "2" tauri-plugin-positioner = "2" reqwest = { version = "0.12.23", features = ["json", "native-tls"] } ts-rs = "11.0.1" +device_query = "4.0.1" +once_cell = "1.21.3" [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] tauri-plugin-global-shortcut = "2" diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index ae8401e..eee5214 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,3 +1,5 @@ +use crate::services::cursor::stream_cursor_position; + static APP_HANDLE: std::sync::OnceLock> = std::sync::OnceLock::new(); mod app; @@ -35,8 +37,7 @@ pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_positioner::init()) - // .plugin(tauri_plugin_global_shortcut::Builder::new().build()) - .invoke_handler(tauri::generate_handler![]) + .invoke_handler(tauri::generate_handler![stream_cursor_position]) .setup(|app| { APP_HANDLE .set(app.handle().to_owned()) diff --git a/src-tauri/src/services/cursor.rs b/src-tauri/src/services/cursor.rs new file mode 100644 index 0000000..feecc7b --- /dev/null +++ b/src-tauri/src/services/cursor.rs @@ -0,0 +1,31 @@ +use device_query::{DeviceEvents, DeviceEventsHandler}; +use serde::Serialize; +use std::time::Duration; +use tauri::ipc::Channel; + +#[derive(Clone, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CursorPosition { + pub x: i32, + pub y: i32, +} + +#[tauri::command] +pub async fn stream_cursor_position(on_event: Channel) { + let device_state = + DeviceEventsHandler::new(Duration::from_millis(200)).expect("Failed to start event loop"); + + let _guard = device_state.on_mouse_move(move |position| { + let pos = CursorPosition { + x: position.0, + y: position.1, + }; + // Ignore send error (e.g. frontend closed channel) + let _ = on_event.send(pos); + }); + + // Prevent function from exiting + loop { + tokio::time::sleep(Duration::ZERO).await; + } +} diff --git a/src-tauri/src/services/mod.rs b/src-tauri/src/services/mod.rs index 2b55280..5fc87e1 100644 --- a/src-tauri/src/services/mod.rs +++ b/src-tauri/src/services/mod.rs @@ -1 +1,2 @@ +pub mod cursor; pub mod overlay; diff --git a/src/channels/cursor.ts b/src/channels/cursor.ts new file mode 100644 index 0000000..b85a475 --- /dev/null +++ b/src/channels/cursor.ts @@ -0,0 +1,12 @@ +import { Channel, invoke } from "@tauri-apps/api/core"; +import { writable } from "svelte/store"; + +export let cursorPositionOnScreen = writable<{ x: number; y: number }>({ x: 0, y: 0 }); + +export function initCursorPositionStream() { + const channel = new Channel<{ x: number; y: number }>(); + channel.onmessage = (pos) => { + cursorPositionOnScreen.set(pos); + }; + invoke("stream_cursor_position", { onEvent: channel }); +} \ No newline at end of file diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 1ab31d7..03aa6e6 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -4,3 +4,6 @@ // See: https://v2.tauri.app/start/frontend/sveltekit/ for more info export const ssr = false; import "../app.css"; +import { initCursorPositionStream } from "../channels/cursor"; + +initCursorPositionStream(); \ No newline at end of file diff --git a/src/routes/scene/+page.svelte b/src/routes/scene/+page.svelte index 5a12d32..ab1bd97 100644 --- a/src/routes/scene/+page.svelte +++ b/src/routes/scene/+page.svelte @@ -1,10 +1,19 @@ + +
-
-
-

Friendolls

-

Scene Screen

-
+
+
+

Friendolls

+

Scene Screen

+
+ Cursor: ({$cursorPositionOnScreen.x}, {$cursorPositionOnScreen.y}) +
+