From 698c447e34f891a72782a30a88a39ccfb6c36e6f Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Tue, 4 Jun 2024 20:42:27 +0900 Subject: [PATCH] fix: mouse click when pointing at 2 screens --- src/backend/openvr/mod.rs | 4 +- src/backend/openxr/mod.rs | 4 +- src/hid.rs | 90 +++++++++++++++++++++++++++------------ src/overlays/screen.rs | 26 ++++++++--- 4 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/backend/openvr/mod.rs b/src/backend/openvr/mod.rs index dc1e1e8..7966dbd 100644 --- a/src/backend/openvr/mod.rs +++ b/src/backend/openvr/mod.rs @@ -296,6 +296,8 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { } } + state.hid_provider.commit(); + lines.update(universe.clone(), &mut overlay_mgr, &mut state)?; for o in overlays.iter_mut() { @@ -324,8 +326,6 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { // chaperone // close font handles? - - state.hid_provider.on_new_frame(); } log::warn!("OpenVR shutdown"); diff --git a/src/backend/openxr/mod.rs b/src/backend/openxr/mod.rs index 02ed27c..8fdb79f 100644 --- a/src/backend/openxr/mod.rs +++ b/src/backend/openxr/mod.rs @@ -256,6 +256,8 @@ pub fn openxr_run(running: Arc) -> Result<(), BackendError> { } } + app_state.hid_provider.commit(); + let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic let watch_transform = watch.state.transform; if !watch.state.want_visible { @@ -376,8 +378,6 @@ pub fn openxr_run(running: Arc) -> Result<(), BackendError> { delete_queue.retain(|(_, frame)| *frame > cur_frame); - app_state.hid_provider.on_new_frame(); - let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic watch.state.transform = watch_transform; } diff --git a/src/hid.rs b/src/hid.rs index 1d49e6f..65d5686 100644 --- a/src/hid.rs +++ b/src/hid.rs @@ -37,21 +37,34 @@ pub fn initialize() -> Box { pub trait HidProvider { fn mouse_move(&mut self, pos: Vec2); - fn send_button(&self, button: u16, down: bool); - fn wheel(&self, delta: i32); + fn send_button(&mut self, button: u16, down: bool); + fn wheel(&mut self, delta: i32); fn set_modifiers(&mut self, mods: u8); fn send_key(&self, key: u16, down: bool); fn set_desktop_extent(&mut self, extent: Vec2); fn set_desktop_origin(&mut self, origin: Vec2); - fn on_new_frame(&mut self); + fn commit(&mut self); +} + +struct MouseButtonAction { + button: u16, + down: bool, +} + +#[derive(Default)] +struct MouseAction { + last_requested_pos: Option, + pos: Option, + button: Option, + scroll: Option, } pub struct UInputProvider { handle: UInputHandle, desktop_extent: Vec2, desktop_origin: Vec2, - mouse_moved: bool, cur_modifiers: u8, + current_action: MouseAction, } pub struct DummyProvider; @@ -145,22 +158,25 @@ impl UInputProvider { handle, desktop_extent: Vec2::ZERO, desktop_origin: Vec2::ZERO, - mouse_moved: false, + current_action: Default::default(), cur_modifiers: 0, }); } } None } -} -impl HidProvider for UInputProvider { - fn mouse_move(&mut self, pos: Vec2) { - if self.mouse_moved { - return; + fn send_button_internal(&self, button: u16, down: bool) { + let time = get_time(); + let events = [ + new_event(time, EV_KEY, button, down as _), + new_event(time, EV_SYN, 0, 0), + ]; + if let Err(res) = self.handle.write(&events) { + log::error!("send_button: {}", res.to_string()); } - self.mouse_moved = true; - + } + fn mouse_move_internal(&mut self, pos: Vec2) { #[cfg(debug_assertions)] log::trace!("Mouse move: {:?}", pos); @@ -176,17 +192,7 @@ impl HidProvider for UInputProvider { log::error!("{}", res.to_string()); } } - fn send_button(&self, button: u16, down: bool) { - let time = get_time(); - let events = [ - new_event(time, EV_KEY, button, down as _), - new_event(time, EV_SYN, 0, 0), - ]; - if let Err(res) = self.handle.write(&events) { - log::error!("send_button: {}", res.to_string()); - } - } - fn wheel(&self, delta: i32) { + fn wheel_internal(&self, delta: i32) { let time = get_time(); let events = [ new_event(time, EV_REL, RelativeAxis::Wheel as _, delta), @@ -196,6 +202,9 @@ impl HidProvider for UInputProvider { log::error!("wheel: {}", res.to_string()); } } +} + +impl HidProvider for UInputProvider { fn set_modifiers(&mut self, modifiers: u8) { let changed = self.cur_modifiers ^ modifiers; for i in 0..7 { @@ -224,20 +233,45 @@ impl HidProvider for UInputProvider { fn set_desktop_origin(&mut self, origin: Vec2) { self.desktop_origin = origin; } - fn on_new_frame(&mut self) { - self.mouse_moved = false; + fn mouse_move(&mut self, pos: Vec2) { + if self.current_action.pos.is_none() { + self.current_action.pos = Some(pos); + } + self.current_action.last_requested_pos = Some(pos); + } + fn send_button(&mut self, button: u16, down: bool) { + if self.current_action.button.is_none() { + self.current_action.button = Some(MouseButtonAction { button, down }); + self.current_action.pos = self.current_action.last_requested_pos; + } + } + fn wheel(&mut self, delta: i32) { + if self.current_action.scroll.is_none() { + self.current_action.scroll = Some(delta); + } + } + fn commit(&mut self) { + if let Some(pos) = self.current_action.pos.take() { + self.mouse_move_internal(pos); + } + if let Some(button) = self.current_action.button.take() { + self.send_button_internal(button.button, button.down); + } + if let Some(scroll) = self.current_action.scroll.take() { + self.wheel_internal(scroll); + } } } impl HidProvider for DummyProvider { fn mouse_move(&mut self, _pos: Vec2) {} - fn send_button(&self, _button: u16, _down: bool) {} - fn wheel(&self, _delta: i32) {} + fn send_button(&mut self, _button: u16, _down: bool) {} + fn wheel(&mut self, _delta: i32) {} fn set_modifiers(&mut self, _modifiers: u8) {} fn send_key(&self, _key: u16, _down: bool) {} fn set_desktop_extent(&mut self, _extent: Vec2) {} fn set_desktop_origin(&mut self, _origin: Vec2) {} - fn on_new_frame(&mut self) {} + fn commit(&mut self) {} } #[inline] diff --git a/src/overlays/screen.rs b/src/overlays/screen.rs index 5971c13..d642a96 100644 --- a/src/overlays/screen.rs +++ b/src/overlays/screen.rs @@ -1,10 +1,11 @@ use core::slice; +use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; use std::{ f32::consts::PI, ops::Add, ptr, - sync::Arc, + sync::{atomic::AtomicU64, Arc}, time::{Duration, Instant}, }; use vulkano::{ @@ -62,9 +63,22 @@ const CURSOR_SIZE: f32 = 16. / 1440.; static DRM_FORMATS: once_cell::sync::OnceCell> = once_cell::sync::OnceCell::new(); +static START: Lazy = Lazy::new(Instant::now); +static NEXT_MOVE: AtomicU64 = AtomicU64::new(0); + +fn can_move() -> bool { + START.elapsed().as_millis() as u64 > NEXT_MOVE.load(std::sync::atomic::Ordering::Relaxed) +} + +fn set_next_move(millis_from_now: u64) { + NEXT_MOVE.store( + START.elapsed().as_millis() as u64 + millis_from_now, + std::sync::atomic::Ordering::Relaxed, + ); +} + pub struct ScreenInteractionHandler { next_scroll: Instant, - next_move: Instant, mouse_transform: Affine2, } impl ScreenInteractionHandler { @@ -90,7 +104,6 @@ impl ScreenInteractionHandler { ScreenInteractionHandler { next_scroll: Instant::now(), - next_move: Instant::now(), mouse_transform: transform, } } @@ -100,7 +113,7 @@ impl InteractionHandler for ScreenInteractionHandler { fn on_hover(&mut self, app: &mut AppState, hit: &PointerHit) -> Option { #[cfg(debug_assertions)] log::trace!("Hover: {:?}", hit.uv); - if self.next_move < Instant::now() + if can_move() && (!app.session.config.focus_follows_mouse_mode || app.input_state.pointers[hit.pointer].now.move_mouse) { @@ -117,8 +130,7 @@ impl InteractionHandler for ScreenInteractionHandler { }; if pressed { - self.next_move = Instant::now() - + Duration::from_millis(app.session.config.click_freeze_time_ms as u64); + set_next_move(app.session.config.click_freeze_time_ms as u64); } app.hid_provider.send_button(btn, pressed); @@ -568,7 +580,7 @@ pub fn create_screen_renderer_wl( capture = Some(renderer); if let Some(token) = restore_token { - if pw_token_store.arc_ins(display_name.into(), token.clone()) { + if pw_token_store.arc_set(display_name.into(), token.clone()) { log::info!("Adding Pipewire token {}", token); } }