mirror of https://github.com/wayvr-org/wayvr.git
mouse wheel handling & wl_virtual modifiers
This commit is contained in:
parent
590980e560
commit
6a6264347b
|
|
@ -121,16 +121,6 @@ impl InputCapture {
|
|||
self.event_rx.try_iter().collect()
|
||||
}
|
||||
|
||||
/// Exclusively grabs every currently detected keyboard and mouse.
|
||||
/// Newly connected matching devices are grabbed automatically.
|
||||
pub fn set_grabbed(&self, grabbed: bool) -> anyhow::Result<()> {
|
||||
self.command_tx
|
||||
.try_send(Command::SetGrabbed(grabbed))
|
||||
.map_err(|error| anyhow::anyhow!("worker thread unreachable: {error}"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set acceleration profile for current and future mice
|
||||
pub fn set_pointer_accel(&self, accel: bool, speed: f32) -> anyhow::Result<()> {
|
||||
if !speed.is_finite() || !(-1.0..=1.0).contains(&speed) {
|
||||
|
|
@ -156,8 +146,12 @@ impl Drop for InputCapture {
|
|||
|
||||
enum Command {
|
||||
ResetWatchdog,
|
||||
SetGrabbed(bool),
|
||||
SetPointerAccel { accel: bool, speed: f32 },
|
||||
#[allow(dead_code)]
|
||||
SetGrabbed(bool), // might need later?
|
||||
SetPointerAccel {
|
||||
accel: bool,
|
||||
speed: f32,
|
||||
},
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ use crate::{
|
|||
subsystem::{
|
||||
dbus::DbusConnector,
|
||||
hid::{self, MODS_TO_KEYS, WheelDelta},
|
||||
input::{HidWrapper, InputFocus},
|
||||
input::HidWrapper,
|
||||
},
|
||||
windowing::{OverlayID, OverlaySelector, backend::OverlayEventData},
|
||||
};
|
||||
|
|
@ -897,7 +897,6 @@ impl WvrServerState {
|
|||
}
|
||||
}
|
||||
input_capture::CapturedEvent::Grabbed => {
|
||||
hid_wrapper.set_input_focus(Some(self), InputFocus::WayVR);
|
||||
audio_sample_player.play_sample(audio_system, "input_grab");
|
||||
if !self.grab_toast_sent {
|
||||
self.grab_toast_sent = true;
|
||||
|
|
|
|||
|
|
@ -352,7 +352,10 @@ impl OverlayBackend for ScreenBackend {
|
|||
.mouse_move(DVec2::new(pos.x as _, pos.y as _));
|
||||
}
|
||||
|
||||
fn on_scroll(&mut self, app: &mut AppState, _hit: &PointerHit, delta: WheelDelta) {
|
||||
fn on_scroll(&mut self, app: &mut AppState, _hit: &PointerHit, mut delta: WheelDelta) {
|
||||
// convert to v120 value; maximum deflect scrolls at half speed
|
||||
delta.x *= 60.0;
|
||||
delta.y *= 60.0;
|
||||
app.hid_provider.inner.wheel(delta);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ impl HidProvider for DummyProvider {
|
|||
fn set_desktop_extent(&mut self, _extent: DVec2) {}
|
||||
fn set_desktop_origin(&mut self, _origin: DVec2) {}
|
||||
fn set_modifiers(&mut self, _modifiers: u8) {}
|
||||
fn send_key(&self, _key: VirtualKey, _down: bool) {}
|
||||
fn send_key(&mut self, _key: VirtualKey, _down: bool) {}
|
||||
|
||||
fn set_keymap(&mut self, _keymap: &XkbKeymap) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub trait HidProvider: Sync + Send {
|
|||
|
||||
// Keyboard Functions
|
||||
fn set_modifiers(&mut self, mods: u8);
|
||||
fn send_key(&self, key: VirtualKey, down: bool);
|
||||
fn send_key(&mut self, key: VirtualKey, down: bool);
|
||||
fn set_keymap(&mut self, keymap: &XkbKeymap);
|
||||
|
||||
// Common Functions
|
||||
|
|
|
|||
|
|
@ -135,18 +135,14 @@ impl UInputProvider {
|
|||
}
|
||||
|
||||
fn wheel_internal(&self, delta: WheelDelta) {
|
||||
let multiplier = 64.0; /* cherry-picked value, overall scrolling speed can be altered via `scroll_speed` in the config */
|
||||
let delta_x = (delta.x * multiplier) as i32;
|
||||
let delta_y = (delta.y * multiplier) as i32;
|
||||
|
||||
let time = get_time();
|
||||
let events = [
|
||||
new_event(time, EV_REL, RelativeAxis::WheelHiRes as _, delta_y),
|
||||
new_event(time, EV_REL, RelativeAxis::WheelHiRes as _, delta.y as _),
|
||||
new_event(
|
||||
time,
|
||||
EV_REL,
|
||||
RelativeAxis::HorizontalWheelHiRes as _,
|
||||
delta_x,
|
||||
delta.x as _,
|
||||
),
|
||||
new_event(time, EV_SYN, 0, 0),
|
||||
];
|
||||
|
|
@ -206,7 +202,7 @@ impl HidProvider for UInputProvider {
|
|||
self.cur_modifiers = modifiers;
|
||||
}
|
||||
|
||||
fn send_key(&self, key: VirtualKey, down: bool) {
|
||||
fn send_key(&mut self, key: VirtualKey, down: bool) {
|
||||
#[cfg(debug_assertions)]
|
||||
log::trace!("send_key: {key:?} {down}");
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::io::Write;
|
|||
use std::os::fd::AsFd;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use anyhow::Context as _;
|
||||
use glam::{DVec2};
|
||||
use glam::{Vec2, DVec2};
|
||||
use input_linux::sys::{*};
|
||||
use smithay::reexports::rustix::fs::{memfd_create, MemfdFlags};
|
||||
use smithay::reexports::wayland_protocols_wlr::virtual_pointer::v1::client::zwlr_virtual_pointer_manager_v1::ZwlrVirtualPointerManagerV1;
|
||||
|
|
@ -21,6 +21,8 @@ use crate::overlays::toast::Toast;
|
|||
use crate::subsystem::hid::provider::HidProvider;
|
||||
use crate::subsystem::hid::{VirtualKey, WheelDelta, *};
|
||||
|
||||
const LOCKED: u8 = CAPS_LOCK | NUM_LOCK;
|
||||
|
||||
pub struct WlVirtualProvider {
|
||||
_connection: wayland_client::Connection,
|
||||
queue: wayland_client::EventQueue<KbState>,
|
||||
|
|
@ -35,6 +37,7 @@ pub struct WlVirtualProvider {
|
|||
keyboard_mods_state: u8,
|
||||
|
||||
last_pointer_position: DVec2,
|
||||
wheel_accum: Vec2,
|
||||
}
|
||||
|
||||
struct KbState;
|
||||
|
|
@ -84,28 +87,30 @@ impl HidProvider for WlVirtualProvider {
|
|||
self.virtual_pointer.frame();
|
||||
}
|
||||
|
||||
fn wheel(&mut self, delta: WheelDelta) {
|
||||
fn wheel(&mut self, mut delta: WheelDelta) {
|
||||
#[cfg(debug_assertions)]
|
||||
log::trace!("Scroll Axis: {delta:?}");
|
||||
|
||||
// no clue; a value of 10 seems to equal a v120 value of 120
|
||||
delta.x /= 12.0;
|
||||
delta.y /= 12.0;
|
||||
|
||||
self.virtual_pointer.axis_source(AxisSource::Wheel);
|
||||
|
||||
if delta.y != 0.0 {
|
||||
let steps = -delta.y.round() as i32;
|
||||
self.virtual_pointer.axis_discrete(
|
||||
Self::now_ms(),
|
||||
Axis::VerticalScroll,
|
||||
steps as f64 * 15.0,
|
||||
steps,
|
||||
-delta.y as _,
|
||||
accumulate_discrete_scroll(&mut self.wheel_accum.y, -delta.y),
|
||||
);
|
||||
}
|
||||
if delta.x != 0.0 {
|
||||
let steps = delta.x.round() as i32;
|
||||
self.virtual_pointer.axis_discrete(
|
||||
Self::now_ms(),
|
||||
Axis::HorizontalScroll,
|
||||
steps as f64 * 15.0,
|
||||
steps,
|
||||
delta.x as _,
|
||||
accumulate_discrete_scroll(&mut self.wheel_accum.x, delta.x),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -122,15 +127,13 @@ impl HidProvider for WlVirtualProvider {
|
|||
}
|
||||
|
||||
fn set_modifiers(&mut self, mods: u8) {
|
||||
const LOCKED: u8 = CAPS_LOCK | NUM_LOCK;
|
||||
|
||||
let changed = (self.keyboard_mods_state ^ mods) & !LOCKED;
|
||||
for bit in [SHIFT, CTRL, ALT, SUPER] {
|
||||
if changed & bit != 0 {
|
||||
let down = mods & bit != 0;
|
||||
if let Some(kc) = Self::modifier_keycode(bit) {
|
||||
if let Some(kc) = MODS_TO_KEYS.get(bit) {
|
||||
self.virtual_keyboard
|
||||
.key(Self::now_ms(), kc - 8, down as u32);
|
||||
.key(Self::now_ms(), kc[0] as u32 - 8, down as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -143,7 +146,7 @@ impl HidProvider for WlVirtualProvider {
|
|||
self._connection.flush().unwrap();
|
||||
}
|
||||
|
||||
fn send_key(&self, key: VirtualKey, down: bool) {
|
||||
fn send_key(&mut self, key: VirtualKey, down: bool) {
|
||||
#[cfg(debug_assertions)]
|
||||
log::trace!("Keyboard key: {key:?} ({}), down: {down}", key as u16);
|
||||
|
||||
|
|
@ -156,6 +159,20 @@ impl HidProvider for WlVirtualProvider {
|
|||
},
|
||||
);
|
||||
|
||||
// sending a mod key → also have to update mod state
|
||||
if let Some(m) = KEYS_TO_MODS.get(key) {
|
||||
match (down, m & LOCKED != 0) {
|
||||
(true, true) => self.keyboard_mods_state ^= m,
|
||||
(true, false) => self.keyboard_mods_state |= m,
|
||||
(false, false) => self.keyboard_mods_state &= !m,
|
||||
(false, true) => {}
|
||||
}
|
||||
|
||||
let depressed = (self.keyboard_mods_state & !LOCKED) as u32;
|
||||
let locked = (self.keyboard_mods_state & LOCKED) as u32;
|
||||
self.virtual_keyboard.modifiers(depressed, 0, locked, 0);
|
||||
}
|
||||
|
||||
self._connection.flush().unwrap();
|
||||
}
|
||||
|
||||
|
|
@ -222,6 +239,7 @@ impl WlVirtualProvider {
|
|||
desktop_origin: DVec2::ZERO,
|
||||
keyboard_mods_state: 0,
|
||||
last_pointer_position: DVec2::ZERO,
|
||||
wheel_accum: Vec2::ZERO,
|
||||
};
|
||||
|
||||
result.set_keymap(&XkbKeymap {
|
||||
|
|
@ -245,17 +263,6 @@ impl WlVirtualProvider {
|
|||
.expect("Failed to compile XKB keymap")
|
||||
}
|
||||
|
||||
fn modifier_keycode(bit: u8) -> Option<u32> {
|
||||
let evdev = match bit {
|
||||
b if b == SHIFT => KEY_LEFTSHIFT,
|
||||
b if b == CTRL => KEY_LEFTCTRL,
|
||||
b if b == ALT => KEY_LEFTALT,
|
||||
b if b == SUPER => KEY_LEFTMETA,
|
||||
_ => return None,
|
||||
};
|
||||
Some(evdev as u32 + 8)
|
||||
}
|
||||
|
||||
fn now_ms() -> u32 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
|
|
@ -292,3 +299,17 @@ pub fn initialize_wl_virtual() -> anyhow::Result<Box<dyn HidProvider>, Toast> {
|
|||
})?;
|
||||
Ok(Box::new(provider))
|
||||
}
|
||||
|
||||
fn accumulate_discrete_scroll(acc: &mut f32, delta: f32) -> i32 {
|
||||
const WHEEL_DETENT: f32 = 10.0;
|
||||
*acc += delta;
|
||||
let steps = (*acc / WHEEL_DETENT).trunc() as i32;
|
||||
if steps != 0 {
|
||||
*acc -= steps as f32 * WHEEL_DETENT;
|
||||
if acc.abs() < 0.001 {
|
||||
*acc = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
steps
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ impl HidWrapper {
|
|||
}
|
||||
|
||||
pub fn send_key_routed(
|
||||
&self,
|
||||
&mut self,
|
||||
wvr_server: Option<&mut WvrServerState>,
|
||||
key: VirtualKey,
|
||||
down: bool,
|
||||
|
|
|
|||
Loading…
Reference in New Issue