use std::time::SystemTime;
use evdev::{EventType, InputEvent, RelativeAxisType};
use crate::config::Settings;
use crate::util::dt_secs;
pub struct Pointer {
last: Option<SystemTime>,
speed: f64, carry_x: f64,
carry_y: f64,
last_gain: f64,
}
impl Pointer {
pub fn new() -> Self {
Pointer {
last: None,
speed: 0.0,
carry_x: 0.0,
carry_y: 0.0,
last_gain: 1.0,
}
}
pub fn speed(&self) -> f64 {
self.speed
}
pub fn gain(&self) -> f64 {
self.last_gain
}
}
fn pointer_gain(c: &Settings, v: f64) -> f64 {
let s = 1.0 / (1.0 + (-(v - c.ptr_mid) / c.ptr_width).exp()); c.ptr_base + (c.ptr_max - c.ptr_base) * s
}
pub fn accel_pointer(
c: &Settings,
p: &mut Pointer,
dx: i32,
dy: i32,
ts: SystemTime,
out: &mut Vec<InputEvent>,
) {
let dt = dt_secs(p.last, ts);
p.last = Some(ts);
let dist = (((dx * dx + dy * dy) as f64).sqrt()).abs();
let v_inst = if dt > 0.0 && dt.is_finite() {
dist / dt
} else {
p.speed
};
let alpha = if dt.is_finite() && dt > 0.0 {
1.0 - (-dt / c.ptr_tau).exp()
} else {
1.0
};
p.speed += alpha * (v_inst - p.speed);
let gain = pointer_gain(c, p.speed);
p.last_gain = gain;
p.carry_x += dx as f64 * gain;
p.carry_y += dy as f64 * gain;
let ox = p.carry_x.trunc() as i32;
let oy = p.carry_y.trunc() as i32;
p.carry_x -= ox as f64;
p.carry_y -= oy as f64;
if c.debug {
eprintln!(
"P dx={dx:+4} dy={dy:+4} v={:7.0} gain={gain:4.2} -> {ox:+4},{oy:+4}",
p.speed
);
}
if ox != 0 {
out.push(InputEvent::new(
EventType::RELATIVE,
RelativeAxisType::REL_X.0,
ox,
));
}
if oy != 0 {
out.push(InputEvent::new(
EventType::RELATIVE,
RelativeAxisType::REL_Y.0,
oy,
));
}
}