added mapped cursor position
This commit is contained in:
@@ -37,5 +37,8 @@ pub async fn initialize_session() {
|
|||||||
overlay_fullscreen(&window).unwrap();
|
overlay_fullscreen(&window).unwrap();
|
||||||
window.set_ignore_cursor_events(true).unwrap();
|
window.set_ignore_cursor_events(true).unwrap();
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
webview_window.open_devtools();
|
||||||
|
|
||||||
println!("Scene window initialized.");
|
println!("Scene window initialized.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::services::cursor::stream_cursor_position;
|
use crate::services::cursor::channel_cursor_positions;
|
||||||
|
|
||||||
static APP_HANDLE: std::sync::OnceLock<tauri::AppHandle<tauri::Wry>> = std::sync::OnceLock::new();
|
static APP_HANDLE: std::sync::OnceLock<tauri::AppHandle<tauri::Wry>> = std::sync::OnceLock::new();
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ pub fn run() {
|
|||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_opener::init())
|
.plugin(tauri_plugin_opener::init())
|
||||||
.plugin(tauri_plugin_positioner::init())
|
.plugin(tauri_plugin_positioner::init())
|
||||||
.invoke_handler(tauri::generate_handler![stream_cursor_position])
|
.invoke_handler(tauri::generate_handler![channel_cursor_positions])
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
APP_HANDLE
|
APP_HANDLE
|
||||||
.set(app.handle().to_owned())
|
.set(app.handle().to_owned())
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ use serde::Serialize;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tauri::ipc::Channel;
|
use tauri::ipc::Channel;
|
||||||
|
|
||||||
|
use crate::get_app_handle;
|
||||||
|
|
||||||
#[derive(Clone, Serialize)]
|
#[derive(Clone, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CursorPosition {
|
pub struct CursorPosition {
|
||||||
@@ -10,22 +12,53 @@ pub struct CursorPosition {
|
|||||||
pub y: i32,
|
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]
|
#[tauri::command]
|
||||||
pub async fn stream_cursor_position(on_event: Channel<CursorPosition>) {
|
pub async fn channel_cursor_positions(on_event: Channel<CursorPositions>) {
|
||||||
|
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<i32> =
|
||||||
|
monitor_dimensions.to_logical(primary_monitor.scale_factor());
|
||||||
let device_state =
|
let device_state =
|
||||||
DeviceEventsHandler::new(Duration::from_millis(200)).expect("Failed to start event loop");
|
DeviceEventsHandler::new(Duration::from_millis(200)).expect("Failed to start event loop");
|
||||||
|
|
||||||
let _guard = device_state.on_mouse_move(move |position| {
|
let _guard = device_state.on_mouse_move(move |position| {
|
||||||
let pos = CursorPosition {
|
let raw = CursorPosition {
|
||||||
x: position.0,
|
x: position.0,
|
||||||
y: position.1,
|
y: position.1,
|
||||||
};
|
};
|
||||||
// Ignore send error (e.g. frontend closed channel)
|
let mapped = map_to_grid(
|
||||||
let _ = on_event.send(pos);
|
&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 {
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,20 +5,19 @@ pub static SCENE_WINDOW_LABEL: &str = "scene";
|
|||||||
pub fn overlay_fullscreen(window: &tauri::Window) -> Result<(), tauri::Error> {
|
pub fn overlay_fullscreen(window: &tauri::Window) -> Result<(), tauri::Error> {
|
||||||
// Get the primary monitor
|
// Get the primary monitor
|
||||||
let monitor = get_app_handle().primary_monitor()?.unwrap();
|
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)
|
// Set window position to top-left
|
||||||
let work_area = monitor.work_area();
|
|
||||||
|
|
||||||
// Set window position to top-left of the work area
|
|
||||||
window.set_position(tauri::PhysicalPosition {
|
window.set_position(tauri::PhysicalPosition {
|
||||||
x: work_area.position.x,
|
x: monitor_position.x,
|
||||||
y: work_area.position.y,
|
y: monitor_position.y,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Set window size to match work area size
|
// Set window size to match screen size
|
||||||
window.set_size(tauri::PhysicalSize {
|
window.set_size(tauri::PhysicalSize {
|
||||||
width: work_area.size.width,
|
width: monitor_size.width,
|
||||||
height: work_area.size.height,
|
height: monitor_size.height,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
import { Channel, invoke } from "@tauri-apps/api/core";
|
import { Channel, invoke } from "@tauri-apps/api/core";
|
||||||
import { writable } from "svelte/store";
|
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<CursorPositions>({
|
||||||
|
raw: { x: 0, y: 0 },
|
||||||
|
mapped: { x: 0, y: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
export function initCursorPositionStream() {
|
export function initChannelCursorPosition() {
|
||||||
const channel = new Channel<{ x: number; y: number }>();
|
const channel = new Channel<CursorPositions>();
|
||||||
channel.onmessage = (pos) => {
|
channel.onmessage = (pos) => {
|
||||||
cursorPositionOnScreen.set(pos);
|
cursorPositionOnScreen.set(pos);
|
||||||
};
|
};
|
||||||
invoke("stream_cursor_position", { onEvent: channel });
|
invoke("channel_cursor_positions", { onEvent: channel });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
||||||
export const ssr = false;
|
export const ssr = false;
|
||||||
import "../app.css";
|
import "../app.css";
|
||||||
import { initCursorPositionStream } from "../channels/cursor";
|
import { initChannelCursorPosition } from "../channels/cursor";
|
||||||
|
|
||||||
initCursorPositionStream();
|
initChannelCursorPosition();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { cursorPositionOnScreen } from "../../channels/cursor";
|
import { cursorPositionOnScreen } from "../../channels/cursor";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-svw h-svh p-4">
|
<div class="w-svw h-svh p-4 relative">
|
||||||
<div
|
<div
|
||||||
class="size-max mx-auto bg-base-100 border-base-200 border px-4 py-3 rounded-xl"
|
class="size-max mx-auto bg-base-100 border-base-200 border px-4 py-3 rounded-xl"
|
||||||
>
|
>
|
||||||
@@ -10,9 +10,14 @@
|
|||||||
<p class="text-xl">Friendolls</p>
|
<p class="text-xl">Friendolls</p>
|
||||||
<p class="text-sm opacity-50">Scene Screen</p>
|
<p class="text-sm opacity-50">Scene Screen</p>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<span class="font-mono"
|
<span class="font-mono">
|
||||||
>Cursor: ({$cursorPositionOnScreen.x}, {$cursorPositionOnScreen.y})</span
|
Cursor: ({$cursorPositionOnScreen.raw.x}, {$cursorPositionOnScreen.raw
|
||||||
>
|
.y})
|
||||||
|
</span>
|
||||||
|
<span class="font-mono">
|
||||||
|
Cursor: ({$cursorPositionOnScreen.mapped.x}, {$cursorPositionOnScreen
|
||||||
|
.mapped.y})
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user