mirror of https://github.com/wayvr-org/wayvr.git
wayvrctl handsfree controls
This commit is contained in:
parent
1f79f231c0
commit
2d820f1d1b
|
|
@ -15,7 +15,7 @@ use tokio_util::sync::CancellationToken;
|
|||
use crate::{
|
||||
gen_id,
|
||||
ipc::{self, Serial},
|
||||
packet_client::{self, PacketClient},
|
||||
packet_client::{self, HandsfreeParams, PacketClient},
|
||||
packet_server::{self, PacketServer},
|
||||
util::notifier::Notifier,
|
||||
};
|
||||
|
|
@ -422,6 +422,14 @@ impl WayVRClient {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn fn_wlx_handsfree(
|
||||
client: WayVRClientMutex,
|
||||
params: HandsfreeParams
|
||||
) -> anyhow::Result<()> {
|
||||
send_only!(client, &PacketClient::WlxHandsfree(params));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn fn_wlx_modify_panel(
|
||||
client: WayVRClientMutex,
|
||||
params: packet_client::WlxModifyPanelParams,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,32 @@ pub enum PositionMode {
|
|||
Static,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub enum HandsfreeMode {
|
||||
None,
|
||||
Hmd,
|
||||
HmdPinch,
|
||||
EyeTracking,
|
||||
EyeTrackingPinch,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub enum HandsfreeAction {
|
||||
Click,
|
||||
Grab,
|
||||
RightModifier,
|
||||
MiddleModifier,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub enum HandsfreeParams {
|
||||
SetMode(HandsfreeMode),
|
||||
Press(HandsfreeAction),
|
||||
Release(HandsfreeAction),
|
||||
Toggle(HandsfreeAction),
|
||||
Scroll(f32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct WvrProcessLaunchParams {
|
||||
pub name: String,
|
||||
|
|
@ -69,4 +95,5 @@ pub enum PacketClient {
|
|||
WlxDeviceHaptics(usize, WlxHapticsParams),
|
||||
WlxShowHide,
|
||||
WlxSwitchSet(Option<usize>),
|
||||
WlxHandsfree(HandsfreeParams),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use glam::{Affine3A, Vec2, Vec3A, Vec3Swizzles};
|
|||
use idmap_derive::IntegerId;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use strum::AsRefStr;
|
||||
use wayvr_ipc::packet_client::{HandsfreeAction, HandsfreeParams};
|
||||
use wlx_common::common::LeftRight;
|
||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||
|
||||
|
|
@ -62,6 +63,7 @@ pub struct InputState {
|
|||
pub ipd: f32,
|
||||
pub pointers: [Pointer; 2],
|
||||
pub devices: Vec<TrackedDevice>,
|
||||
pub handsfree_state: PointerState,
|
||||
processes: Vec<Child>,
|
||||
}
|
||||
|
||||
|
|
@ -73,9 +75,44 @@ impl InputState {
|
|||
pointers: [Pointer::new(0), Pointer::new(1)],
|
||||
devices: Vec::new(),
|
||||
processes: Vec::new(),
|
||||
handsfree_state: PointerState::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_handsfree_action(&mut self, params: HandsfreeParams) {
|
||||
fn set_true(v: &mut bool) {
|
||||
*v = true;
|
||||
}
|
||||
fn set_false(v: &mut bool) {
|
||||
*v = false;
|
||||
}
|
||||
fn toggle(v: &mut bool) {
|
||||
*v = !*v;
|
||||
}
|
||||
|
||||
let (action, apply) = match params {
|
||||
HandsfreeParams::SetMode(_) => {
|
||||
return;
|
||||
}
|
||||
HandsfreeParams::Press(action) => (action, set_true as fn(&mut bool)),
|
||||
HandsfreeParams::Release(action) => (action, set_false as fn(&mut bool)),
|
||||
HandsfreeParams::Toggle(action) => (action, toggle as fn(&mut bool)),
|
||||
HandsfreeParams::Scroll(val) => {
|
||||
self.handsfree_state.scroll_y = val;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match action {
|
||||
HandsfreeAction::Click => apply(&mut self.handsfree_state.click),
|
||||
HandsfreeAction::RightModifier => apply(&mut self.handsfree_state.click_modifier_right),
|
||||
HandsfreeAction::MiddleModifier => {
|
||||
apply(&mut self.handsfree_state.click_modifier_middle)
|
||||
}
|
||||
HandsfreeAction::Grab => apply(&mut self.handsfree_state.grab),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn handle_task(&mut self, task: InputTask) {
|
||||
match task {
|
||||
InputTask::Haptics { device, haptics } => {
|
||||
|
|
@ -271,7 +308,7 @@ impl Pointer {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct PointerState {
|
||||
pub scroll_x: f32,
|
||||
pub scroll_y: f32,
|
||||
|
|
@ -350,7 +387,7 @@ fn populate_lines(
|
|||
|
||||
// horizontal arm
|
||||
lines.push(PointerLine {
|
||||
mode: PointerMode::Left,
|
||||
mode: hit.mode,
|
||||
a: raw_hit.global_pos - (hmd.x_axis * HALF_SIZE),
|
||||
b: raw_hit.global_pos + (hmd.x_axis * HALF_SIZE),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ use wlx_common::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
backend::input::{Haptics, InputState, Pointer, TrackedDevice, TrackedDeviceRole},
|
||||
backend::input::{
|
||||
Haptics, InputState, Pointer, PointerState, TrackedDevice, TrackedDeviceRole,
|
||||
},
|
||||
state::{AppSession, AppState},
|
||||
};
|
||||
|
||||
|
|
@ -246,6 +248,7 @@ impl OpenXrInputSource {
|
|||
&state.session,
|
||||
hmd,
|
||||
hmd_tracked,
|
||||
&state.input_state.handsfree_state,
|
||||
)?;
|
||||
}
|
||||
|
||||
|
|
@ -349,6 +352,7 @@ impl OpenXrPointer {
|
|||
session: &AppSession,
|
||||
hmd: Affine3A,
|
||||
hmd_tracked: bool,
|
||||
handsfree_state: &PointerState,
|
||||
) -> anyhow::Result<()> {
|
||||
match session.config.handsfree_pointer {
|
||||
HandsfreePointer::None => return Ok(()),
|
||||
|
|
@ -379,11 +383,21 @@ impl OpenXrPointer {
|
|||
session.config.handsfree_pointer,
|
||||
HandsfreePointer::HmdOnly | HandsfreePointer::EyeTrackingOnly
|
||||
) {
|
||||
// skip actions
|
||||
// input from wayvrctl
|
||||
pointer.now.click = handsfree_state.click;
|
||||
pointer.now.grab = handsfree_state.grab;
|
||||
pointer.now.click_modifier_right = handsfree_state.click_modifier_right;
|
||||
pointer.now.click_modifier_middle = handsfree_state.click_modifier_middle;
|
||||
pointer.now.scroll_y = handsfree_state.scroll_y;
|
||||
|
||||
// skip action loading
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.pointer_load_actions(pointer, xr)?;
|
||||
pointer.now.click_modifier_right = handsfree_state.click_modifier_right;
|
||||
pointer.now.click_modifier_middle = handsfree_state.click_modifier_middle;
|
||||
pointer.now.scroll_y = handsfree_state.scroll_y;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use wayvr_ipc::packet_client::{HandsfreeMode, HandsfreeParams};
|
||||
use wayvr_ipc::packet_server;
|
||||
use wlx_common::config::HandsfreePointer;
|
||||
|
||||
use crate::backend::wayvr::{self, WvrServerState};
|
||||
|
||||
|
|
@ -58,6 +60,19 @@ where
|
|||
app.tasks
|
||||
.enqueue(TaskType::Overlay(OverlayTask::ModifyPanel(custom_task)));
|
||||
}
|
||||
WayVRSignal::Handsfree(params) => match params {
|
||||
HandsfreeParams::SetMode(mode) => {
|
||||
let mode = match mode {
|
||||
HandsfreeMode::None => HandsfreePointer::None,
|
||||
HandsfreeMode::Hmd => HandsfreePointer::HmdOnly,
|
||||
HandsfreeMode::HmdPinch => HandsfreePointer::Hmd,
|
||||
HandsfreeMode::EyeTracking => HandsfreePointer::EyeTrackingOnly,
|
||||
HandsfreeMode::EyeTrackingPinch => HandsfreePointer::EyeTracking,
|
||||
};
|
||||
app.session.config.handsfree_pointer = mode;
|
||||
}
|
||||
_ => app.input_state.apply_handsfree_action(params),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use glam::Vec3A;
|
|||
use interprocess::local_socket::{self, ToNsName, traits::Listener};
|
||||
use smallvec::SmallVec;
|
||||
use std::io::{Read, Write};
|
||||
use wayvr_ipc::packet_client::HandsfreeParams;
|
||||
use wayvr_ipc::{
|
||||
ipc::{self},
|
||||
packet_client::{self, PacketClient},
|
||||
|
|
@ -356,6 +357,10 @@ impl Connection {
|
|||
params.signals.send(WayVRSignal::SwitchSet(set));
|
||||
}
|
||||
|
||||
fn handle_wlx_handsfree(params: &mut TickParams, payload: HandsfreeParams) {
|
||||
params.signals.send(WayVRSignal::Handsfree(payload));
|
||||
}
|
||||
|
||||
fn handle_wlx_panel(
|
||||
params: &mut TickParams,
|
||||
custom_params: packet_client::WlxModifyPanelParams,
|
||||
|
|
@ -433,6 +438,9 @@ impl Connection {
|
|||
PacketClient::WlxModifyPanel(custom_params) => {
|
||||
Self::handle_wlx_panel(params, custom_params);
|
||||
}
|
||||
PacketClient::WlxHandsfree(payload) => {
|
||||
Self::handle_wlx_handsfree(params, payload);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ pub enum WayVRSignal {
|
|||
BroadcastStateChanged(wayvr_ipc::packet_server::WvrStateChanged),
|
||||
DeviceHaptics(usize, crate::backend::input::Haptics),
|
||||
SwitchSet(Option<usize>),
|
||||
Handsfree(wayvr_ipc::packet_client::HandsfreeParams),
|
||||
ShowHide,
|
||||
CustomTask(crate::backend::task::ModifyPanelTask),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use serde::Serialize;
|
|||
use wayvr_ipc::{
|
||||
client::{WayVRClient, WayVRClientMutex},
|
||||
ipc,
|
||||
packet_client::{self, PositionMode},
|
||||
packet_client::{self, HandsfreeParams, PositionMode},
|
||||
packet_server,
|
||||
};
|
||||
|
||||
|
|
@ -173,6 +173,14 @@ pub async fn wlx_switch_set(state: &mut WayVRClientState, set: Option<usize>) {
|
|||
)
|
||||
}
|
||||
|
||||
pub async fn wlx_handsfree(state: &mut WayVRClientState, params: HandsfreeParams) {
|
||||
handle_empty_result(
|
||||
WayVRClient::fn_wlx_handsfree(state.wayvr_client.clone(), params)
|
||||
.await
|
||||
.context("failed to set handsfree mode"),
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn wlx_panel_modify(
|
||||
state: &mut WayVRClientState,
|
||||
overlay: String,
|
||||
|
|
|
|||
|
|
@ -14,12 +14,13 @@ use wayvr_ipc::{
|
|||
};
|
||||
|
||||
use crate::helper::{
|
||||
WayVRClientState, wlx_device_haptics, wlx_input_state, wlx_panel_modify, wlx_show_hide,
|
||||
wlx_switch_set, wvr_process_get, wvr_process_launch, wvr_process_list, wvr_process_terminate,
|
||||
wvr_window_list, wvr_window_set_visible,
|
||||
WayVRClientState, wlx_device_haptics, wlx_handsfree, wlx_input_state, wlx_panel_modify,
|
||||
wlx_show_hide, wlx_switch_set, wvr_process_get, wvr_process_launch, wvr_process_list,
|
||||
wvr_process_terminate, wvr_window_list, wvr_window_set_visible,
|
||||
};
|
||||
|
||||
mod helper;
|
||||
mod types;
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> ExitCode {
|
||||
|
|
@ -195,6 +196,9 @@ async fn run_once(state: &mut WayVRClientState, args: Args) -> anyhow::Result<()
|
|||
let set = if set == 0 { None } else { Some((set - 1) as _) };
|
||||
wlx_switch_set(state, set).await;
|
||||
}
|
||||
Subcommands::Handsfree { command } => {
|
||||
wlx_handsfree(state, command.into()).await;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -291,6 +295,11 @@ enum Subcommands {
|
|||
/// Set number to switch to, 0 to hide all sets
|
||||
set_or_0: usize,
|
||||
},
|
||||
Handsfree {
|
||||
/// Command to execute
|
||||
#[command(subcommand)]
|
||||
command: SubcommandHandsfree,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, clap::ValueEnum)]
|
||||
|
|
@ -300,6 +309,47 @@ enum PosModeEnum {
|
|||
Static,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, clap::ValueEnum)]
|
||||
pub enum HandsfreeMode {
|
||||
/// No handsfree pointer control
|
||||
None,
|
||||
/// Pointer controlled by HMD
|
||||
Hmd,
|
||||
/// Pointer controlled by HMD. Left pinch click, right pinch grab.
|
||||
HmdPinch,
|
||||
/// Pointer controlled by eye gaze
|
||||
EyeTracking,
|
||||
/// Pointer controlled eye gaze. Left pinch click, right pinch grab.
|
||||
EyeTrackingPinch,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, clap::ValueEnum)]
|
||||
pub enum HandsfreeAction {
|
||||
/// The click action
|
||||
Click,
|
||||
/// The grab action
|
||||
Grab,
|
||||
/// Right-click modifier (use with click)
|
||||
RightModifier,
|
||||
/// Middle-click modifier (use with click)
|
||||
MiddleModifier,
|
||||
}
|
||||
|
||||
#[derive(clap::Parser, Debug)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub enum SubcommandHandsfree {
|
||||
/// Set the handsfree mode
|
||||
SetMode { mode: HandsfreeMode },
|
||||
/// Press and hold an action
|
||||
Press { action: HandsfreeAction },
|
||||
/// Release a held action
|
||||
Release { action: HandsfreeAction },
|
||||
/// Toggle the state of an action
|
||||
Toggle { action: HandsfreeAction },
|
||||
/// Emulate a joystick scroll
|
||||
Scroll { amount: f32 },
|
||||
}
|
||||
|
||||
#[derive(clap::Parser, Debug)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
enum SubcommandPanelModify {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
use wayvr_ipc::packet_client as ipc;
|
||||
|
||||
impl From<crate::HandsfreeMode> for ipc::HandsfreeMode {
|
||||
fn from(mode: crate::HandsfreeMode) -> Self {
|
||||
match mode {
|
||||
crate::HandsfreeMode::None => Self::None,
|
||||
crate::HandsfreeMode::Hmd => Self::Hmd,
|
||||
crate::HandsfreeMode::HmdPinch => Self::HmdPinch,
|
||||
crate::HandsfreeMode::EyeTracking => Self::EyeTracking,
|
||||
crate::HandsfreeMode::EyeTrackingPinch => Self::EyeTrackingPinch,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::HandsfreeAction> for ipc::HandsfreeAction {
|
||||
fn from(action: crate::HandsfreeAction) -> Self {
|
||||
match action {
|
||||
crate::HandsfreeAction::Click => Self::Click,
|
||||
crate::HandsfreeAction::Grab => Self::Grab,
|
||||
crate::HandsfreeAction::RightModifier => Self::RightModifier,
|
||||
crate::HandsfreeAction::MiddleModifier => Self::MiddleModifier,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::SubcommandHandsfree> for ipc::HandsfreeParams {
|
||||
fn from(cmd: crate::SubcommandHandsfree) -> Self {
|
||||
match cmd {
|
||||
crate::SubcommandHandsfree::SetMode { mode } => Self::SetMode(mode.into()),
|
||||
crate::SubcommandHandsfree::Press { action } => Self::Press(action.into()),
|
||||
crate::SubcommandHandsfree::Release { action } => Self::Release(action.into()),
|
||||
crate::SubcommandHandsfree::Toggle { action } => Self::Toggle(action.into()),
|
||||
crate::SubcommandHandsfree::Scroll { amount } => Self::Scroll(amount),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue