diff --git a/src/controller/controls/scroll_mt.rs b/src/controller/controls/scroll_mt.rs index 921a0b2..7854669 100644 --- a/src/controller/controls/scroll_mt.rs +++ b/src/controller/controls/scroll_mt.rs @@ -2,14 +2,55 @@ use crate::controller::{ControlMode, ControlModeMeta}; use crate::dial_device::DialHaptics; use crate::error::{Error, Result}; use crate::fake_input; +use std::sync::{Arc, Mutex}; +use std::thread::{self, JoinHandle}; +use std::time::{Duration, Instant}; pub struct ScrollMT { acc_delta: i32, + last_dial_time: Arc>>, + stop_thread: Arc>, + is_scrolling: Arc>, + timer_thread: Option>, // Add this to store the thread handle } impl ScrollMT { pub fn new() -> ScrollMT { - ScrollMT { acc_delta: 0 } + ScrollMT { + acc_delta: 0, + last_dial_time: Arc::new(Mutex::new(None)), + stop_thread: Arc::new(Mutex::new(false)), + is_scrolling: Arc::new(Mutex::new(false)), + timer_thread: None, + } + } + + fn start_timer_thread(&mut self) { + // Reset the stop signal + *self.stop_thread.lock().unwrap() = false; + + let last_dial_time = Arc::clone(&self.last_dial_time); + let stop_thread = Arc::clone(&self.stop_thread); + let is_scrolling = Arc::clone(&self.is_scrolling); + + self.timer_thread = Some(thread::spawn(move || { + while !(*stop_thread.lock().unwrap()) { + thread::sleep(Duration::from_millis(100)); + + let mut last_time = last_dial_time.lock().unwrap(); + let mut scrolling = is_scrolling.lock().unwrap(); + + if let Some(last) = *last_time { + if last.elapsed() > Duration::from_millis(100) && *scrolling { + if let Err(e) = fake_input::scroll_mt_end() { + eprintln!("Error ending scroll: {:?}", e); + } + *last_time = None; + *scrolling = false; + } + } + } + })); } } @@ -25,37 +66,60 @@ impl ControlMode for ScrollMT { fn on_start(&mut self, _haptics: &DialHaptics) -> Result<()> { self.acc_delta = 0; + *self.last_dial_time.lock().unwrap() = None; + *self.is_scrolling.lock().unwrap() = true; - // HACK: for some reason, if scroll mode is the startup mode, then just calling - // `scroll_mt_start` doesn't work as expected. - std::thread::spawn(move || { - fake_input::scroll_mt_end().unwrap(); - std::thread::sleep(std::time::Duration::from_millis(200)); - fake_input::scroll_mt_start().unwrap(); - }); + fake_input::scroll_mt_start().map_err(Error::Evdev)?; + + // Start a new timer thread + self.start_timer_thread(); Ok(()) } fn on_end(&mut self, _haptics: &DialHaptics) -> Result<()> { + // Signal the timer thread to stop + *self.stop_thread.lock().unwrap() = true; + + // Wait for the timer thread to finish + if let Some(thread) = self.timer_thread.take() { + let _ = thread.join(); + } + + // End multitouch scrolling fake_input::scroll_mt_end().map_err(Error::Evdev)?; Ok(()) } - // HACK: the button will reset the scroll event, which sometimes helps - fn on_btn_press(&mut self, _: &DialHaptics) -> Result<()> { + // End multitouch scrolling on button press fake_input::scroll_mt_end().map_err(Error::Evdev)?; + *self.is_scrolling.lock().unwrap() = false; Ok(()) } fn on_btn_release(&mut self, _haptics: &DialHaptics) -> Result<()> { + // Restart multitouch scrolling on button release fake_input::scroll_mt_start().map_err(Error::Evdev)?; + *self.is_scrolling.lock().unwrap() = true; Ok(()) } fn on_dial(&mut self, _: &DialHaptics, delta: i32) -> Result<()> { self.acc_delta += delta; + + // Update the last dial time + let mut last_dial_time = self.last_dial_time.lock().unwrap(); + *last_dial_time = Some(Instant::now()); + + // Restart multitouch scrolling if it was inactive + let mut scrolling = self.is_scrolling.lock().unwrap(); + if !*scrolling { + fake_input::scroll_mt_start().map_err(Error::Evdev)?; + *scrolling = true; + } + + // Perform a multitouch scroll step fake_input::scroll_mt_step(self.acc_delta).map_err(Error::Evdev)?; Ok(()) diff --git a/src/fake_input.rs b/src/fake_input.rs index 2a8a1ac..6320b78 100644 --- a/src/fake_input.rs +++ b/src/fake_input.rs @@ -7,7 +7,7 @@ use parking_lot::ReentrantMutex; // this should be a fairly high number, as the axis is from 0..(MT_BASELINE*2) const MT_BASELINE: i32 = std::i32::MAX / 8; // higher = slower scrolling -const MT_SENSITIVITY: i32 = 48; +const MT_SENSITIVITY: i32 = 32; pub struct FakeInputs { keyboard: ReentrantMutex,