mirror of https://github.com/wayvr-org/wayvr.git
input capture #4 - pointer accel config
This commit is contained in:
parent
8e87e8cc2a
commit
2633022304
|
|
@ -163,7 +163,10 @@
|
|||
"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_ACCELERATION": "Mouse acceleration",
|
||||
"POINTER_ACCELERATION_HELP": "On: Adaptive mouse acceleration\nOff: Constant speed",
|
||||
"POINTER_LERP_FACTOR": "Pointer smoothing",
|
||||
"POINTER_SPEED": "Mouse speed",
|
||||
"REQUIRES_RESTART": "Requires restart",
|
||||
"RESET_PLAYSPACE": "Reset playspace",
|
||||
"RESET_PLAYSPACE_HELP": "Clear the stage space offset.",
|
||||
|
|
|
|||
|
|
@ -300,6 +300,7 @@ pub(crate) enum SettingType {
|
|||
ClickFreezeTimeMs,
|
||||
Clock12h,
|
||||
DoubleCursorFix,
|
||||
EnableWatch,
|
||||
FocusFollowsMouseMode,
|
||||
GridOpacity,
|
||||
HandsfreePointer,
|
||||
|
|
@ -317,11 +318,12 @@ pub(crate) enum SettingType {
|
|||
NotificationsSoundEnabled,
|
||||
DefaultOverlayScale,
|
||||
OpaqueBackground,
|
||||
MouseAcceleration,
|
||||
PointerLerpFactor,
|
||||
MouseSpeed,
|
||||
ScreenRenderDown,
|
||||
ScrollSpeed,
|
||||
SnapAngleDeg,
|
||||
EnableWatch,
|
||||
SetsOnWatch,
|
||||
SpaceDragMultiplier,
|
||||
SpaceDragUnlocked,
|
||||
|
|
@ -346,6 +348,7 @@ pub(crate) enum SettingType {
|
|||
impl SettingType {
|
||||
pub fn change_kind(self) -> ConfigChangeKind {
|
||||
match self {
|
||||
Self::MouseAcceleration | Self::MouseSpeed => ConfigChangeKind::WvrServerConfig,
|
||||
Self::UseSkybox | Self::UsePassthrough => ConfigChangeKind::EnvironmentBlend,
|
||||
_ => ConfigChangeKind::OverlayConfig,
|
||||
}
|
||||
|
|
@ -370,6 +373,7 @@ impl SettingType {
|
|||
Self::NotificationsEnabled => &mut config.notifications_enabled,
|
||||
Self::NotificationsSoundEnabled => &mut config.notifications_sound_enabled,
|
||||
Self::OpaqueBackground => &mut config.opaque_background,
|
||||
Self::MouseAcceleration => &mut config.wvr_mouse_acceleration,
|
||||
Self::ScreenRenderDown => &mut config.screen_render_down,
|
||||
Self::SetsOnWatch => &mut config.sets_on_watch,
|
||||
Self::SpaceDragUnlocked => &mut config.space_drag_unlocked,
|
||||
|
|
@ -389,6 +393,7 @@ impl SettingType {
|
|||
Self::GridOpacity => &mut config.grid_opacity,
|
||||
Self::LongPressDuration => &mut config.long_press_duration,
|
||||
Self::PointerLerpFactor => &mut config.pointer_lerp_factor,
|
||||
Self::MouseSpeed => &mut config.wvr_mouse_speed,
|
||||
Self::ScrollSpeed => &mut config.scroll_speed,
|
||||
Self::SnapAngleDeg => &mut config.snap_angle_deg,
|
||||
Self::SpaceDragMultiplier => &mut config.space_drag_multiplier,
|
||||
|
|
@ -497,6 +502,8 @@ impl SettingType {
|
|||
Self::NotificationsEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_ENABLED"),
|
||||
Self::NotificationsSoundEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_SOUND_ENABLED"),
|
||||
Self::OpaqueBackground => Ok("APP_SETTINGS.OPAQUE_BACKGROUND"),
|
||||
Self::MouseSpeed => Ok("APP_SETTINGS.POINTER_SPEED"),
|
||||
Self::MouseAcceleration => Ok("APP_SETTINGS.POINTER_ACCELERATION"),
|
||||
Self::PointerLerpFactor => Ok("APP_SETTINGS.POINTER_LERP_FACTOR"),
|
||||
Self::ScreenRenderDown => Ok("APP_SETTINGS.SCREEN_RENDER_DOWN"),
|
||||
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
|
||||
|
|
@ -538,6 +545,7 @@ impl SettingType {
|
|||
Self::InputEmulationMethod => Some("APP_SETTINGS.INPUT_EMULATION_METHOD_HELP"),
|
||||
Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"),
|
||||
Self::LeftHandedMouse => Some("APP_SETTINGS.LEFT_HANDED_MOUSE_HELP"),
|
||||
Self::MouseAcceleration => Some("APP_SETTINGS.POINTER_ACCELERATION_HELP"),
|
||||
Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"),
|
||||
Self::SnapAngleDeg => Some("APP_SETTINGS.SNAP_ANGLE_DEG_HELP"),
|
||||
Self::SpaceGravityDamping => Some("APP_SETTINGS.SPACE_GRAVITY_DAMPING_HELP"),
|
||||
|
|
|
|||
|
|
@ -112,6 +112,9 @@ impl State {
|
|||
|
||||
options_slider_i32(par.mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50)?;
|
||||
|
||||
options_slider_f32(par.mp, c, SettingType::MouseSpeed, -1., 1., 0.05)?;
|
||||
options_checkbox(par.mp, c, SettingType::MouseAcceleration)?;
|
||||
|
||||
Ok(State {
|
||||
popup_input_profiles: popup,
|
||||
frontend_tasks: par.frontend_tasks.clone(),
|
||||
|
|
|
|||
|
|
@ -51,31 +51,16 @@ pub enum CapturedEvent {
|
|||
UngrabbedAll,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum PointerAccelProfile {
|
||||
Adaptive,
|
||||
Flat,
|
||||
}
|
||||
|
||||
impl PointerAccelProfile {
|
||||
fn to_libinput(self) -> AccelProfile {
|
||||
match self {
|
||||
Self::Adaptive => AccelProfile::Adaptive,
|
||||
Self::Flat => AccelProfile::Flat,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct PointerAccelConfig {
|
||||
profile: PointerAccelProfile,
|
||||
speed: f64,
|
||||
accel: bool,
|
||||
speed: f32,
|
||||
}
|
||||
|
||||
impl Default for PointerAccelConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
profile: PointerAccelProfile::Adaptive,
|
||||
accel: true,
|
||||
speed: 0.0,
|
||||
}
|
||||
}
|
||||
|
|
@ -143,17 +128,13 @@ impl InputCapture {
|
|||
}
|
||||
|
||||
/// Set acceleration profile for current and future mice
|
||||
pub fn set_pointer_accel(
|
||||
&self,
|
||||
profile: PointerAccelProfile,
|
||||
speed: f64,
|
||||
) -> anyhow::Result<()> {
|
||||
pub fn set_pointer_accel(&self, accel: bool, speed: f32) -> anyhow::Result<()> {
|
||||
if !speed.is_finite() || !(-1.0..=1.0).contains(&speed) {
|
||||
anyhow::bail!("pointer acceleration speed must be within -1.0..=1.0");
|
||||
}
|
||||
|
||||
self.command_tx
|
||||
.send(Command::SetPointerAccel { profile, speed })
|
||||
.send(Command::SetPointerAccel { accel, speed })
|
||||
.map_err(|error| anyhow::anyhow!("worker thread unreachable: {error}"))?;
|
||||
|
||||
Ok(())
|
||||
|
|
@ -176,8 +157,8 @@ enum Command {
|
|||
response_tx: SyncSender<io::Result<()>>,
|
||||
},
|
||||
SetPointerAccel {
|
||||
profile: PointerAccelProfile,
|
||||
speed: f64,
|
||||
accel: bool,
|
||||
speed: f32,
|
||||
},
|
||||
Shutdown,
|
||||
}
|
||||
|
|
@ -400,8 +381,8 @@ fn worker_main(
|
|||
|
||||
let _ = response_tx.send(result);
|
||||
}
|
||||
Ok(Command::SetPointerAccel { profile, speed }) => {
|
||||
pointer_accel = PointerAccelConfig { profile, speed };
|
||||
Ok(Command::SetPointerAccel { accel, speed }) => {
|
||||
pointer_accel = PointerAccelConfig { accel, speed };
|
||||
for mut device in pointer_devices.iter().cloned() {
|
||||
apply_pointer_accel(&mut device, pointer_accel);
|
||||
}
|
||||
|
|
@ -640,11 +621,15 @@ fn apply_pointer_accel(device: &mut LibinputDevice, config: PointerAccelConfig)
|
|||
return;
|
||||
}
|
||||
|
||||
let profile = config.profile.to_libinput();
|
||||
let profile = if config.accel {
|
||||
AccelProfile::Adaptive
|
||||
} else {
|
||||
AccelProfile::Flat
|
||||
};
|
||||
if device.config_accel_profiles().contains(&profile) {
|
||||
let _ = device.config_accel_set_profile(profile);
|
||||
}
|
||||
let _ = device.config_accel_set_speed(config.speed);
|
||||
let _ = device.config_accel_set_speed(config.speed as _);
|
||||
}
|
||||
|
||||
fn drain_pending_libinput_events(
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ pub mod window;
|
|||
|
||||
use anyhow::Context;
|
||||
use comp::Application;
|
||||
use glam::Vec2;
|
||||
use glam::{DVec2, Vec2};
|
||||
use process::ProcessVec;
|
||||
use slotmap::SecondaryMap;
|
||||
use smallvec::SmallVec;
|
||||
|
|
@ -57,7 +57,7 @@ use wayland_protocols::xdg::shell::server::xdg_toplevel;
|
|||
use wayvr_ipc::{packet_client::PositionMode, packet_server};
|
||||
use wgui::{gfx::WGfx, log::LogErr};
|
||||
use wlx_capture::frame::Transform;
|
||||
use wlx_common::desktop_finder::DesktopFinder;
|
||||
use wlx_common::{config::GeneralConfig, desktop_finder::DesktopFinder};
|
||||
use xkbcommon::xkb;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -615,6 +615,14 @@ impl WvrServerState {
|
|||
Ok(tasks)
|
||||
}
|
||||
|
||||
pub fn config_changed(&mut self, config: &GeneralConfig) {
|
||||
if let Some(cap) = self.input_capture.as_mut() {
|
||||
let _ = cap
|
||||
.set_pointer_accel(config.wvr_mouse_acceleration, config.wvr_mouse_speed)
|
||||
.log_err("Could not set mouse accel/speed");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn terminate_process(
|
||||
&mut self,
|
||||
process_handle: process::ProcessHandle,
|
||||
|
|
@ -719,6 +727,8 @@ impl WvrServerState {
|
|||
return;
|
||||
};
|
||||
|
||||
let mut mouse_delta = DVec2::ZERO;
|
||||
|
||||
for ev in input_capture.drain_events() {
|
||||
match ev {
|
||||
input_capture::CapturedEvent::Key { code, pressed } => {
|
||||
|
|
@ -765,36 +775,7 @@ impl WvrServerState {
|
|||
);
|
||||
}
|
||||
input_capture::CapturedEvent::PointerMotion { dx, dy } => {
|
||||
let Some(ref hover) = self.wm.mouse else {
|
||||
continue;
|
||||
};
|
||||
let new_x = hover.x as f64 + dx;
|
||||
let new_y = hover.y as f64 + dy;
|
||||
let new_pos = Vec2::new(new_x as f32, new_y as f32);
|
||||
|
||||
let Some(window) = self.wm.windows.get(&hover.hover_window) else {
|
||||
continue;
|
||||
};
|
||||
let toplevel = window.toplevel.wl_surface().clone();
|
||||
let inner_extent = with_states(&toplevel, |states| {
|
||||
SurfaceBufWithImage::get_from_surface(states)
|
||||
.map(|s| s.image.extent_u32arr())
|
||||
.unwrap_or([1, 1])
|
||||
});
|
||||
let Some(hit_ctx) = build_hit_context(
|
||||
&toplevel,
|
||||
&self.manager.state.popup_manager,
|
||||
inner_extent,
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
let target = hit_ctx.hit_target_at(new_pos);
|
||||
let focus_target = self.hit_target_to_focus(
|
||||
target.unwrap_or(WvrHitTarget::Toplevel { pos: new_pos }),
|
||||
hover.hover_window,
|
||||
new_pos,
|
||||
);
|
||||
self.send_mouse_move(focus_target, new_pos, hover.hover_window);
|
||||
mouse_delta += DVec2 { x: dx, y: dy };
|
||||
}
|
||||
input_capture::CapturedEvent::PointerAxis {
|
||||
horizontal_v120,
|
||||
|
|
@ -819,6 +800,40 @@ impl WvrServerState {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if mouse_delta.length_squared() > 1e-6 {
|
||||
'mouse_update: {
|
||||
let Some(ref hover) = self.wm.mouse else {
|
||||
break 'mouse_update;
|
||||
};
|
||||
|
||||
let new_x = hover.x as f64 + mouse_delta.x;
|
||||
let new_y = hover.y as f64 + mouse_delta.y;
|
||||
let new_pos = Vec2::new(new_x as f32, new_y as f32);
|
||||
|
||||
let Some(window) = self.wm.windows.get(&hover.hover_window) else {
|
||||
break 'mouse_update;
|
||||
};
|
||||
let toplevel = window.toplevel.wl_surface().clone();
|
||||
let inner_extent = with_states(&toplevel, |states| {
|
||||
SurfaceBufWithImage::get_from_surface(states)
|
||||
.map(|s| s.image.extent_u32arr())
|
||||
.unwrap_or([1, 1])
|
||||
});
|
||||
let Some(hit_ctx) =
|
||||
build_hit_context(&toplevel, &self.manager.state.popup_manager, inner_extent)
|
||||
else {
|
||||
break 'mouse_update;
|
||||
};
|
||||
let target = hit_ctx.hit_target_at(new_pos);
|
||||
let focus_target = self.hit_target_to_focus(
|
||||
target.unwrap_or(WvrHitTarget::Toplevel { pos: new_pos }),
|
||||
hover.hover_window,
|
||||
new_pos,
|
||||
);
|
||||
self.send_mouse_move(focus_target, new_pos, hover.hover_window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn button_to_mouse_index(button: u32) -> Option<MouseIndex> {
|
||||
|
|
|
|||
|
|
@ -188,6 +188,8 @@ pub struct AutoSettings {
|
|||
pub default_overlay_scale: f32,
|
||||
pub color_palette: Arc<str>,
|
||||
pub snap_angle_deg: f32,
|
||||
pub wvr_mouse_acceleration: bool,
|
||||
pub wvr_mouse_speed: f32,
|
||||
}
|
||||
|
||||
fn get_settings_path() -> PathBuf {
|
||||
|
|
@ -254,6 +256,8 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
|
|||
default_overlay_scale: config.default_overlay_scale,
|
||||
color_palette: config.color_palette.clone(),
|
||||
snap_angle_deg: config.snap_angle_deg,
|
||||
wvr_mouse_acceleration: config.wvr_mouse_acceleration,
|
||||
wvr_mouse_speed: config.wvr_mouse_speed,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string_pretty(&conf).unwrap(); // want panic
|
||||
|
|
|
|||
|
|
@ -543,6 +543,11 @@ impl DashInterface<AppState> for DashInterfaceLive {
|
|||
.enqueue(TaskType::OpenXR(OpenXrTask::EnvironmentChanged));
|
||||
}
|
||||
}
|
||||
ConfigChangeKind::WvrServerConfig => {
|
||||
if let Some(wvr_server) = data.wvr_server.as_mut() {
|
||||
wvr_server.config_changed(&data.session.config);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,10 +205,6 @@ const fn def_true() -> bool {
|
|||
true
|
||||
}
|
||||
|
||||
const fn def_false() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
const fn def_one() -> f32 {
|
||||
1.0
|
||||
}
|
||||
|
|
@ -225,10 +221,6 @@ const fn def_point3() -> f32 {
|
|||
0.3
|
||||
}
|
||||
|
||||
const fn def_zero() -> f32 {
|
||||
0.0
|
||||
}
|
||||
|
||||
const fn def_osc_port() -> u16 {
|
||||
9000
|
||||
}
|
||||
|
|
@ -245,10 +237,6 @@ fn def_timezones() -> Vec<String> {
|
|||
}
|
||||
}
|
||||
|
||||
fn def_empty() -> Arc<str> {
|
||||
"".into()
|
||||
}
|
||||
|
||||
fn def_default() -> Arc<str> {
|
||||
"Default".into()
|
||||
}
|
||||
|
|
@ -287,10 +275,10 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_click_freeze_time_ms")]
|
||||
pub click_freeze_time_ms: i32,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub invert_scroll_direction_x: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub invert_scroll_direction_y: bool,
|
||||
|
||||
#[serde(default = "def_one")]
|
||||
|
|
@ -329,19 +317,19 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_osc_port")]
|
||||
pub osc_out_port: u16,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub upright_screen_fix: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub double_cursor_fix: bool,
|
||||
|
||||
#[serde(default = "def_true")]
|
||||
pub enable_watch: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub sets_on_watch: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub hide_grab_help: bool,
|
||||
|
||||
#[serde(default)]
|
||||
|
|
@ -356,13 +344,13 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_true")]
|
||||
pub allow_sliding: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub focus_follows_mouse_mode: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub left_handed_mouse: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub block_game_input: bool,
|
||||
|
||||
#[serde(default = "def_true")]
|
||||
|
|
@ -374,7 +362,7 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_one")]
|
||||
pub space_drag_multiplier: f32,
|
||||
|
||||
#[serde(default = "def_empty")]
|
||||
#[serde(default)]
|
||||
pub skybox_texture: Arc<str>,
|
||||
|
||||
#[serde(default = "def_true")]
|
||||
|
|
@ -386,7 +374,7 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_max_height")]
|
||||
pub screen_max_height: u16,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub screen_render_down: bool,
|
||||
|
||||
#[serde(default = "def_point3")]
|
||||
|
|
@ -395,10 +383,10 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_true")]
|
||||
pub space_drag_unlocked: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub space_rotate_unlocked: bool,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub space_gravity_enabled: bool,
|
||||
|
||||
#[serde(default = "def_one")]
|
||||
|
|
@ -413,7 +401,7 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_one")]
|
||||
pub space_gravity_ground_friction: f32,
|
||||
|
||||
#[serde(default = "def_zero")]
|
||||
#[serde(default)]
|
||||
pub space_gravity_floor_height: f32,
|
||||
|
||||
#[serde(default)]
|
||||
|
|
@ -425,7 +413,7 @@ pub struct GeneralConfig {
|
|||
#[serde(default = "def_timezones")]
|
||||
pub timezones: Vec<String>,
|
||||
|
||||
#[serde(default = "def_false")]
|
||||
#[serde(default)]
|
||||
pub clock_12h: bool,
|
||||
|
||||
#[serde(default)]
|
||||
|
|
@ -470,7 +458,7 @@ pub struct GeneralConfig {
|
|||
#[serde(default)]
|
||||
pub tutorial_graduated: bool,
|
||||
|
||||
#[serde(default = "def_empty")]
|
||||
#[serde(default)]
|
||||
pub whisper_model: Arc<str>,
|
||||
|
||||
#[serde(default = "def_default")]
|
||||
|
|
@ -478,4 +466,10 @@ pub struct GeneralConfig {
|
|||
|
||||
#[serde(default)]
|
||||
pub snap_angle_deg: f32,
|
||||
|
||||
#[serde(default = "def_true")]
|
||||
pub wvr_mouse_acceleration: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub wvr_mouse_speed: f32,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ pub enum ConfigChangeKind {
|
|||
OverlayConfig,
|
||||
EnvironmentBlend,
|
||||
WguiThemeChange, // TODO: does not do anything right now
|
||||
WvrServerConfig,
|
||||
/// Marks the config for saving but doesn't notify any components
|
||||
#[default]
|
||||
Other,
|
||||
|
|
|
|||
Loading…
Reference in New Issue