add setting for input provider

This commit is contained in:
galister 2026-07-02 17:36:20 +09:00
parent 07b7d89be6
commit 34bd920f3b
8 changed files with 62 additions and 6 deletions

View File

@ -115,6 +115,8 @@
"HANDSFREE_POINTER_HELP": "Input to use when motion\ncontrollers are unavailable.\nLeft pinch is grab, right is click.", "HANDSFREE_POINTER_HELP": "Input to use when motion\ncontrollers are unavailable.\nLeft pinch is grab, right is click.",
"HIDE_GRAB_HELP": "Hide grab help", "HIDE_GRAB_HELP": "Hide grab help",
"HIDE_USERNAME": "Hide username", "HIDE_USERNAME": "Hide username",
"INPUT_EMULATION_METHOD": "Input emulation method",
"INPUT_EMULATION_METHOD_HELP": "Try change this in case mouse or\nkeyboard input does not register.",
"INPUT_PROFILES": "Change Input Bindings", "INPUT_PROFILES": "Change Input Bindings",
"INPUT_PROFILES_HELP": "OpenXR controller input bindings", "INPUT_PROFILES_HELP": "OpenXR controller input bindings",
"INVERT_SCROLL_DIRECTION_X": "Invert horizontal scroll direction", "INVERT_SCROLL_DIRECTION_X": "Invert horizontal scroll direction",
@ -141,10 +143,15 @@
"HMD_ONLY": "HMD only", "HMD_ONLY": "HMD only",
"HMD_PINCH": "HMD + pinch", "HMD_PINCH": "HMD + pinch",
"NONE": "None", "NONE": "None",
"NONE_INPUT_HELP": "Do not emulate mouse and keyboard.\nWill not be able to interact with screens.",
"PIPEWIRE_HELP": "Fast GPU capture,\nstandard on all desktops.", "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", "PW_FALLBACK_HELP": "Slow method with high CPU usage.\nTry in case PipeWire GPU doesn't work",
"SCREENCOPY_GPU_HELP": "Fast, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway", "SCREENCOPY_GPU_HELP": "Fast, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "Slow, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway" "SCREENCOPY_HELP": "Slow, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway",
"UINPUT": "Device emulation",
"UINPUT_HELP": "Uses the uinput module to emulate a device.\nYour user must be in the input group.\nKnown to work well on most desktops.",
"WL_VIRTUAL": "Wayland virtual input",
"WL_VIRTUAL_HELP": "Send events to the Wayland compositor using\nzwlr_virtual_pointer and zwp_virtual_keyboard.\nOnly works reliably on some desktops.\nDoes NOT work on KDE, GNOME or COSMIC."
}, },
"POINTER_LERP_FACTOR": "Pointer smoothing", "POINTER_LERP_FACTOR": "Pointer smoothing",
"REQUIRES_RESTART": "Requires restart", "REQUIRES_RESTART": "Requires restart",

View File

@ -284,6 +284,7 @@ enum SettingType {
HandsfreePointer, HandsfreePointer,
HideGrabHelp, HideGrabHelp,
HideUsername, HideUsername,
InputEmulationMethod,
InvertScrollDirectionX, InvertScrollDirectionX,
InvertScrollDirectionY, InvertScrollDirectionY,
KeyboardMiddleClick, KeyboardMiddleClick,
@ -392,6 +393,10 @@ impl SettingType {
Self::CaptureMethod => { Self::CaptureMethod => {
config.capture_method = wlx_common::config::CaptureMethod::from_str(value).expect("Invalid enum value!") config.capture_method = wlx_common::config::CaptureMethod::from_str(value).expect("Invalid enum value!")
} }
Self::InputEmulationMethod => {
config.input_emulation_method =
wlx_common::config::InputEmulationMethod::from_str(value).expect("Invalid enum value!")
}
Self::KeyboardMiddleClick => { Self::KeyboardMiddleClick => {
config.keyboard_middle_click_mode = config.keyboard_middle_click_mode =
wlx_common::config::AltModifier::from_str(value).expect("Invalid enum value!") wlx_common::config::AltModifier::from_str(value).expect("Invalid enum value!")
@ -409,6 +414,7 @@ impl SettingType {
fn get_enum_title(self, config: &mut GeneralConfig) -> Translation { fn get_enum_title(self, config: &mut GeneralConfig) -> Translation {
match self { match self {
Self::CaptureMethod => Self::get_enum_title_inner(config.capture_method), Self::CaptureMethod => Self::get_enum_title_inner(config.capture_method),
Self::InputEmulationMethod => Self::get_enum_title_inner(config.input_emulation_method),
Self::KeyboardMiddleClick => Self::get_enum_title_inner(config.keyboard_middle_click_mode), Self::KeyboardMiddleClick => Self::get_enum_title_inner(config.keyboard_middle_click_mode),
Self::HandsfreePointer => Self::get_enum_title_inner(config.handsfree_pointer), Self::HandsfreePointer => Self::get_enum_title_inner(config.handsfree_pointer),
Self::Language => match &config.language { Self::Language => match &config.language {
@ -454,6 +460,7 @@ impl SettingType {
Self::HandsfreePointer => Ok("APP_SETTINGS.HANDSFREE_POINTER"), Self::HandsfreePointer => Ok("APP_SETTINGS.HANDSFREE_POINTER"),
Self::HideGrabHelp => Ok("APP_SETTINGS.HIDE_GRAB_HELP"), Self::HideGrabHelp => Ok("APP_SETTINGS.HIDE_GRAB_HELP"),
Self::HideUsername => Ok("APP_SETTINGS.HIDE_USERNAME"), Self::HideUsername => Ok("APP_SETTINGS.HIDE_USERNAME"),
Self::InputEmulationMethod => Ok("APP_SETTINGS.INPUT_EMULATION_METHOD"),
Self::InvertScrollDirectionX => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_X"), Self::InvertScrollDirectionX => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_X"),
Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"), Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"),
Self::KeyboardMiddleClick => Ok("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK"), Self::KeyboardMiddleClick => Ok("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK"),
@ -500,6 +507,7 @@ impl SettingType {
Self::DoubleCursorFix => Some("APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP"), Self::DoubleCursorFix => Some("APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP"),
Self::GridOpacity => Some("APP_SETTINGS.GRID_OPACITY_HELP"), Self::GridOpacity => Some("APP_SETTINGS.GRID_OPACITY_HELP"),
Self::HandsfreePointer => Some("APP_SETTINGS.HANDSFREE_POINTER_HELP"), Self::HandsfreePointer => Some("APP_SETTINGS.HANDSFREE_POINTER_HELP"),
Self::InputEmulationMethod => Some("APP_SETTINGS.INPUT_EMULATION_METHOD_HELP"),
Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"), Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"),
Self::LeftHandedMouse => Some("APP_SETTINGS.LEFT_HANDED_MOUSE_HELP"), Self::LeftHandedMouse => Some("APP_SETTINGS.LEFT_HANDED_MOUSE_HELP"),
Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"), Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"),
@ -527,6 +535,7 @@ impl SettingType {
| Self::DoubleCursorFix | Self::DoubleCursorFix
| Self::Language | Self::Language
| Self::CaptureMethod | Self::CaptureMethod
| Self::InputEmulationMethod
) )
} }

View File

@ -10,6 +10,7 @@ impl SettingsTab for State {}
impl State { impl State {
pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> { pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> {
let c = options_category(par.mp, par.id_parent, "APP_SETTINGS.MISC", "dashboard/blocks.svg")?; let c = options_category(par.mp, par.id_parent, "APP_SETTINGS.MISC", "dashboard/blocks.svg")?;
options_dropdown::<wlx_common::config::InputEmulationMethod>(par.mp, c, &SettingType::InputEmulationMethod)?;
options_dropdown::<wlx_common::config::CaptureMethod>(par.mp, c, &SettingType::CaptureMethod)?; options_dropdown::<wlx_common::config::CaptureMethod>(par.mp, c, &SettingType::CaptureMethod)?;
options_checkbox(par.mp, c, SettingType::XwaylandByDefault)?; options_checkbox(par.mp, c, SettingType::XwaylandByDefault)?;
options_checkbox(par.mp, c, SettingType::UprightScreenFix)?; options_checkbox(par.mp, c, SettingType::UprightScreenFix)?;

View File

@ -469,7 +469,9 @@ fn input_controls_for_hand(
clicks_dropdown(mp, parent, action.clone(), click_type)?; clicks_dropdown(mp, parent, action.clone(), click_type)?;
if let Some(component) = current.as_ref().map(|x| x.component) if let Some(component) = current.as_ref().map(|x| x.component)
&& component.is_analog() && &*action != "scroll" // hax && component.is_analog()
&& &*action != "scroll"
// hax
{ {
threshold_slider(mp, parent, action, side, threshold)?; threshold_slider(mp, parent, action, side, threshold)?;
} }

View File

@ -92,7 +92,7 @@ impl AppState {
.log_err("Could not initialize WayVR Server") .log_err("Could not initialize WayVR Server")
.ok(); .ok();
let (hid_provider, mut hid_error) = HidWrapper::new(); let (hid_provider, mut hid_error) = HidWrapper::new(session.config.input_emulation_method);
#[cfg(feature = "osc")] #[cfg(feature = "osc")]
let osc_sender = crate::subsystem::osc::OscSender::new(session.config.osc_out_port).ok(); let osc_sender = crate::subsystem::osc::OscSender::new(session.config.osc_out_port).ok();

View File

@ -1,3 +1,4 @@
use crate::overlays::toast::Toast;
use crate::subsystem::hid::provider::HidProvider; use crate::subsystem::hid::provider::HidProvider;
use crate::subsystem::hid::{VirtualKey, WheelDelta, XkbKeymap}; use crate::subsystem::hid::{VirtualKey, WheelDelta, XkbKeymap};
use glam::Vec2; use glam::Vec2;
@ -17,3 +18,7 @@ impl HidProvider for DummyProvider {
fn commit(&mut self) {} fn commit(&mut self) {}
} }
pub fn initialize_dummy() -> anyhow::Result<Box<dyn HidProvider>, Toast> {
Ok(Box::new(DummyProvider {}))
}

View File

@ -1,3 +1,5 @@
use wlx_common::config::InputEmulationMethod;
use super::hid::{self, VirtualKey}; use super::hid::{self, VirtualKey};
use crate::subsystem::hid::provider::HidProvider; use crate::subsystem::hid::provider::HidProvider;
@ -17,9 +19,14 @@ pub struct HidWrapper {
} }
impl HidWrapper { impl HidWrapper {
pub fn new() -> (Self, Option<Toast>) { pub fn new(method: InputEmulationMethod) -> (Self, Option<Toast>) {
let (provider, toast) = hid::provider::wl_virtual::initialize_wl_virtual() let maybe_provider = match method {
.or_else(|_| hid::provider::uinput::initialize_uinput()) InputEmulationMethod::Uinput => hid::provider::uinput::initialize_uinput(),
InputEmulationMethod::WlVirtual => hid::provider::wl_virtual::initialize_wl_virtual(),
InputEmulationMethod::None => hid::provider::dummy::initialize_dummy(),
};
let (provider, toast) = maybe_provider
.map(|provider| (provider, None)) .map(|provider| (provider, None))
.unwrap_or_else(|toast| (Box::new(DummyProvider {}), Some(toast))); .unwrap_or_else(|toast| (Box::new(DummyProvider {}), Some(toast)));

View File

@ -40,6 +40,28 @@ pub enum CaptureMethod {
ScreenCopyCpu, ScreenCopyCpu,
} }
#[derive(Default, Clone, Copy, Serialize, Deserialize, AsRefStr, EnumString, EnumProperty, VariantArray)]
pub enum InputEmulationMethod {
#[default]
#[strum(props(
Translation = "APP_SETTINGS.OPTION.UINPUT",
Tooltip = "APP_SETTINGS.OPTION.UINPUT_HELP"
))]
Uinput,
#[strum(props(
Translation = "APP_SETTINGS.OPTION.WL_VIRTUAL",
Tooltip = "APP_SETTINGS.OPTION.WL_VIRTUAL_HELP"
))]
WlVirtual,
#[strum(props(
Translation = "APP_SETTINGS.OPTION.NONE",
Tooltip = "APP_SETTINGS.OPTION.NONE_INPUT_HELP"
))]
None,
}
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, AsRefStr, EnumString, EnumProperty, VariantArray)] #[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, AsRefStr, EnumString, EnumProperty, VariantArray)]
pub enum AltModifier { pub enum AltModifier {
#[default] #[default]
@ -292,6 +314,9 @@ pub struct GeneralConfig {
#[serde(default)] #[serde(default)]
pub capture_method: CaptureMethod, pub capture_method: CaptureMethod,
#[serde(default)]
pub input_emulation_method: InputEmulationMethod,
#[serde(default = "def_true")] #[serde(default = "def_true")]
pub allow_sliding: bool, pub allow_sliding: bool,