diff --git a/src-tauri/src/app.rs b/src-tauri/src/app.rs index 52d8525..aa39406 100644 --- a/src-tauri/src/app.rs +++ b/src-tauri/src/app.rs @@ -37,5 +37,8 @@ pub async fn initialize_session() { overlay_fullscreen(&window).unwrap(); window.set_ignore_cursor_events(true).unwrap(); + #[cfg(debug_assertions)] + webview_window.open_devtools(); + println!("Scene window initialized."); } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index eee5214..6571d91 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,4 +1,4 @@ -use crate::services::cursor::stream_cursor_position; +use crate::services::cursor::channel_cursor_positions; static APP_HANDLE: std::sync::OnceLock> = std::sync::OnceLock::new(); @@ -37,7 +37,7 @@ pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_positioner::init()) - .invoke_handler(tauri::generate_handler![stream_cursor_position]) + .invoke_handler(tauri::generate_handler![channel_cursor_positions]) .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 index feecc7b..faa5116 100644 --- a/src-tauri/src/services/cursor.rs +++ b/src-tauri/src/services/cursor.rs @@ -3,6 +3,8 @@ use serde::Serialize; use std::time::Duration; use tauri::ipc::Channel; +use crate::get_app_handle; + #[derive(Clone, Serialize)] #[serde(rename_all = "camelCase")] pub struct CursorPosition { @@ -10,22 +12,53 @@ pub struct CursorPosition { pub y: i32, } +#[derive(Clone, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CursorPositions { + pub raw: CursorPosition, + pub mapped: CursorPosition, +} + +fn map_to_grid( + pos: &CursorPosition, + grid_size: i32, + screen_w: i32, + screen_h: i32, +) -> CursorPosition { + CursorPosition { + x: pos.x * grid_size / screen_w, + y: pos.y * grid_size / screen_h, + } +} + #[tauri::command] -pub async fn stream_cursor_position(on_event: Channel) { +pub async fn channel_cursor_positions(on_event: Channel) { + let app_handle = get_app_handle(); + let primary_monitor = app_handle.primary_monitor().unwrap().unwrap(); + let monitor_dimensions = primary_monitor.size(); + let logical_monitor_dimensions: tauri::LogicalSize = + monitor_dimensions.to_logical(primary_monitor.scale_factor()); 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 { + let raw = CursorPosition { x: position.0, y: position.1, }; - // Ignore send error (e.g. frontend closed channel) - let _ = on_event.send(pos); + let mapped = map_to_grid( + &raw, + 600, + logical_monitor_dimensions.width, + logical_monitor_dimensions.height, + ); + let positions = CursorPositions { raw, mapped }; + let _ = on_event.send(positions); }); - // Prevent function from exiting loop { - tokio::time::sleep(Duration::ZERO).await; + // for whatever reason this sleep is not taking effect but it + // does reduce CPU usage on my Mac from 100% to 6% so...cool! + tokio::time::sleep(Duration::from_millis(1000)).await } } diff --git a/src-tauri/src/services/overlay.rs b/src-tauri/src/services/overlay.rs index a74512e..9f0b07f 100644 --- a/src-tauri/src/services/overlay.rs +++ b/src-tauri/src/services/overlay.rs @@ -5,20 +5,19 @@ pub static SCENE_WINDOW_LABEL: &str = "scene"; pub fn overlay_fullscreen(window: &tauri::Window) -> Result<(), tauri::Error> { // Get the primary monitor let monitor = get_app_handle().primary_monitor()?.unwrap(); + let monitor_position = monitor.position(); + let monitor_size = monitor.size(); - // Get the work area (usable space, excluding menu bar/dock/notch) - let work_area = monitor.work_area(); - - // Set window position to top-left of the work area + // Set window position to top-left window.set_position(tauri::PhysicalPosition { - x: work_area.position.x, - y: work_area.position.y, + x: monitor_position.x, + y: monitor_position.y, })?; - // Set window size to match work area size + // Set window size to match screen size window.set_size(tauri::PhysicalSize { - width: work_area.size.width, - height: work_area.size.height, + width: monitor_size.width, + height: monitor_size.height, })?; Ok(()) diff --git a/src/channels/cursor.ts b/src/channels/cursor.ts index b85a475..50ccc25 100644 --- a/src/channels/cursor.ts +++ b/src/channels/cursor.ts @@ -1,12 +1,19 @@ 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 type CursorPositions = { + raw: { x: number; y: number }; + mapped: { x: number; y: number }; +}; +export let cursorPositionOnScreen = writable({ + raw: { x: 0, y: 0 }, + mapped: { x: 0, y: 0 }, +}); -export function initCursorPositionStream() { - const channel = new Channel<{ x: number; y: number }>(); +export function initChannelCursorPosition() { + const channel = new Channel(); channel.onmessage = (pos) => { cursorPositionOnScreen.set(pos); }; - invoke("stream_cursor_position", { onEvent: channel }); -} \ No newline at end of file + invoke("channel_cursor_positions", { onEvent: channel }); +} diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 03aa6e6..b0c4d63 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -4,6 +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"; +import { initChannelCursorPosition } from "../channels/cursor"; -initCursorPositionStream(); \ No newline at end of file +initChannelCursorPosition(); diff --git a/src/routes/scene/+page.svelte b/src/routes/scene/+page.svelte index ab1bd97..8b2eeae 100644 --- a/src/routes/scene/+page.svelte +++ b/src/routes/scene/+page.svelte @@ -2,7 +2,7 @@ import { cursorPositionOnScreen } from "../../channels/cursor"; -
+
@@ -10,9 +10,14 @@

Friendolls

Scene Screen

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