From 3ec1dd7f4ee1d462868f23d17162edd567c9e2bb Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Sun, 25 Jan 2026 11:43:44 +0900 Subject: [PATCH] mouse-motion-only handsfree modes --- dash-frontend/assets/lang/en.json | 2 ++ wayvr/src/assets/gui/keyboard.xml | 2 ++ wayvr/src/assets/lang/en.json | 4 +++- wayvr/src/backend/openxr/input.rs | 12 ++++++++++-- wayvr/src/overlays/watch.rs | 8 ++------ wayvr/src/windowing/manager.rs | 1 - wlx-common/src/config.rs | 4 ++++ 7 files changed, 23 insertions(+), 10 deletions(-) diff --git a/dash-frontend/assets/lang/en.json b/dash-frontend/assets/lang/en.json index 0773522..c5c98d4 100644 --- a/dash-frontend/assets/lang/en.json +++ b/dash-frontend/assets/lang/en.json @@ -74,6 +74,8 @@ "AUTO_HELP": "ScreenCopy GPU if supported,\notherwise PipeWire GPU.", "EYE_PINCH": "Eye + pinch", "HMD_PINCH": "HMD + pinch", + "EYE_ONLY": "Eye only", + "HMD_ONLY": "HMD only", "NONE": "None", "PIPEWIRE_HELP": "Fast GPU capture,\nstandard on all desktops.", "PW_FALLBACK_HELP": "Slow method with high CPU usage.\nTry in case PipeWire GPU doesn't work", diff --git a/wayvr/src/assets/gui/keyboard.xml b/wayvr/src/assets/gui/keyboard.xml index 38ab3dc..5de2e66 100644 --- a/wayvr/src/assets/gui/keyboard.xml +++ b/wayvr/src/assets/gui/keyboard.xml @@ -167,7 +167,9 @@ + + diff --git a/wayvr/src/assets/lang/en.json b/wayvr/src/assets/lang/en.json index 55525d4..2c176fe 100644 --- a/wayvr/src/assets/lang/en.json +++ b/wayvr/src/assets/lang/en.json @@ -17,7 +17,9 @@ "TITLE": "Handsfree mode", "NONE": "Off", "HMD": "HMD + pinch", - "EYE_TRACKING": "Eye + pinch" + "EYE_TRACKING": "Eye + pinch", + "HMD_ONLY": "HMD only", + "EYE_ONLY": "Eye only" } }, "DEFAULT": "Default", diff --git a/wayvr/src/backend/openxr/input.rs b/wayvr/src/backend/openxr/input.rs index 5a64911..0569a05 100644 --- a/wayvr/src/backend/openxr/input.rs +++ b/wayvr/src/backend/openxr/input.rs @@ -348,7 +348,7 @@ impl OpenXrPointer { ) -> anyhow::Result<()> { match session.config.handsfree_pointer { HandsfreePointer::None => return Ok(()), - HandsfreePointer::Hmd => { + HandsfreePointer::Hmd | HandsfreePointer::HmdOnly => { pointer.tracked = hmd_tracked; pointer.raw_pose = hmd; pointer.pose = hmd; @@ -364,13 +364,21 @@ impl OpenXrPointer { cur_pos.lerp(new_pos.into(), lerp_factor).into(), ); } - HandsfreePointer::EyeTracking => { + HandsfreePointer::EyeTracking | HandsfreePointer::EyeTrackingOnly => { // more aggressive smoothing for eye self.pointer_load_pose(pointer, xr, session.config.pointer_lerp_factor * 0.5)?; } } pointer.handsfree = pointer.tracked; + if matches!( + session.config.handsfree_pointer, + HandsfreePointer::HmdOnly | HandsfreePointer::EyeTrackingOnly + ) { + // skip actions + return Ok(()); + } + self.pointer_load_actions(pointer, xr, session)?; Ok(()) diff --git a/wayvr/src/overlays/watch.rs b/wayvr/src/overlays/watch.rs index d7c20d6..60a9bf6 100644 --- a/wayvr/src/overlays/watch.rs +++ b/wayvr/src/overlays/watch.rs @@ -1,6 +1,6 @@ use std::{rc::Rc, time::Duration}; -use glam::{Affine3A, Quat, Vec3, Vec3A, vec3}; +use glam::{Affine3A, Quat, Vec3, vec3}; use wgui::{ assets::AssetPath, components::button::ComponentButton, @@ -23,11 +23,7 @@ use crate::{ timer::GuiTimer, }, state::AppState, - windowing::{ - Z_ORDER_WATCH, - backend::OverlayEventData, - window::{OverlayWindowConfig, OverlayWindowData}, - }, + windowing::{Z_ORDER_WATCH, backend::OverlayEventData, window::OverlayWindowConfig}, }; pub const WATCH_NAME: &str = "watch"; diff --git a/wayvr/src/windowing/manager.rs b/wayvr/src/windowing/manager.rs index 45fa4ae..283b0c3 100644 --- a/wayvr/src/windowing/manager.rs +++ b/wayvr/src/windowing/manager.rs @@ -12,7 +12,6 @@ use wlx_common::{ astr_containers::{AStrMap, AStrMapExt}, config::SerializedWindowSet, overlays::{BackendAttrib, BackendAttribValue, ToastTopic}, - windowing::Positioning, }; use crate::{ diff --git a/wlx-common/src/config.rs b/wlx-common/src/config.rs index eb0018b..faede03 100644 --- a/wlx-common/src/config.rs +++ b/wlx-common/src/config.rs @@ -57,8 +57,12 @@ pub enum HandsfreePointer { #[strum(props(Translation = "APP_SETTINGS.OPTION.HMD_PINCH"))] #[default] Hmd, + #[strum(props(Translation = "APP_SETTINGS.OPTION.HMD_ONLY"))] + HmdOnly, #[strum(props(Translation = "APP_SETTINGS.OPTION.EYE_PINCH"))] EyeTracking, + #[strum(props(Translation = "APP_SETTINGS.OPTION.EYE_ONLY"))] + EyeTrackingOnly, } #[derive(Clone, Serialize, Deserialize)]