#[cfg(target_os = "linux")]
pub(crate) mod keymap;
#[cfg(target_os = "linux")]
pub(crate) mod uinput;
#[cfg(target_os = "linux")]
pub mod portal;
use auv_driver_common::error::DriverResult;
use auv_driver_common::input::Scroll;
pub(crate) const SCROLL_PIXELS_PER_WHEEL_NOTCH: f64 = 120.0;
pub(crate) const HI_RES_UNITS_PER_WHEEL_NOTCH: f64 = 120.0;
pub(crate) fn wheel_notches(remainder: (f64, f64), scroll: Scroll) -> DriverResult<((i32, i32), (f64, f64))> {
wheel_steps(remainder, scroll, 1.0 / SCROLL_PIXELS_PER_WHEEL_NOTCH)
}
pub(crate) fn wheel_hi_res_units(remainder: (f64, f64), scroll: Scroll) -> DriverResult<((i32, i32), (f64, f64))> {
let per_pixel = HI_RES_UNITS_PER_WHEEL_NOTCH / SCROLL_PIXELS_PER_WHEEL_NOTCH;
wheel_steps(remainder, scroll, per_pixel)
}
fn wheel_steps(remainder: (f64, f64), scroll: Scroll, steps_per_pixel: f64) -> DriverResult<((i32, i32), (f64, f64))> {
if !scroll.delta_x.is_finite() || !scroll.delta_y.is_finite() {
return Err(crate::error::invalid_input("scroll delta must be finite"));
}
let x = remainder.0 + scroll.delta_x * steps_per_pixel;
let y = remainder.1 + scroll.delta_y * steps_per_pixel;
if x.abs() > f64::from(i32::MAX) || y.abs() > f64::from(i32::MAX) {
return Err(crate::error::invalid_input("scroll delta exceeds the wheel range"));
}
Ok(((x.trunc() as i32, y.trunc() as i32), (x.fract(), y.fract())))
}
#[cfg(test)]
mod wheel_tests {
use super::*;
#[test]
fn wheel_notches_map_120_logical_pixels_to_one_notch_toward_later_content() {
assert_eq!(wheel_notches((0.0, 0.0), Scroll::new(0.0, 120.0)).unwrap(), ((0, 1), (0.0, 0.0)));
assert_eq!(wheel_notches((0.0, 0.0), Scroll::new(240.0, -360.0)).unwrap(), ((2, -3), (0.0, 0.0)));
let (notches, remainder) = wheel_notches((0.0, 0.0), Scroll::new(0.0, 60.0)).unwrap();
assert_eq!(notches, (0, 0));
assert_eq!(wheel_notches(remainder, Scroll::new(0.0, 60.0)).unwrap(), ((0, 1), (0.0, 0.0)));
assert!(wheel_notches((0.0, 0.0), Scroll::new(f64::NAN, 0.0)).is_err());
}
#[test]
fn wheel_hi_res_units_map_one_logical_pixel_to_one_unit_and_carry_fractions() {
assert_eq!(wheel_hi_res_units((0.0, 0.0), Scroll::new(-30.0, 45.0)).unwrap(), ((-30, 45), (0.0, 0.0)));
let (units, remainder) = wheel_hi_res_units((0.0, 0.0), Scroll::new(0.0, 0.6)).unwrap();
assert_eq!(units, (0, 0));
assert_eq!(wheel_hi_res_units(remainder, Scroll::new(0.0, 0.6)).unwrap().0, (0, 1));
}
}
#[cfg(not(target_os = "linux"))]
pub mod portal {
use auv_driver_common::error::{DriverError, DriverResult};
use auv_driver_common::geometry::Point;
use auv_driver_common::input::{Click, Scroll};
#[derive(Debug, Default)]
pub struct PortalClipboard;
impl PortalClipboard {
pub fn open(_app_id: Option<&String>) -> DriverResult<ClipboardSession> {
Err(DriverError::unsupported("linux.portal.clipboard"))
}
}
#[derive(Debug, Default)]
pub struct ClipboardSession;
impl ClipboardSession {
pub fn snapshot(&mut self) -> DriverResult<String> {
Err(DriverError::unsupported("linux.portal.clipboard"))
}
pub fn set_text(&mut self, _text: &str) -> DriverResult<()> {
Err(DriverError::unsupported("linux.portal.clipboard"))
}
}
#[derive(Debug, Default)]
pub struct PortalInput;
impl PortalInput {
pub fn open(_restore_tokens: Option<&RestoreTokenStore>, _app_id: Option<&String>) -> DriverResult<InputSession> {
Err(DriverError::unsupported("linux.portal.input"))
}
}
#[derive(Clone, Debug, Default)]
pub struct RestoreTokenStore;
impl RestoreTokenStore {
pub(crate) fn new(_root: std::path::PathBuf) -> Self {
Self
}
}
#[derive(Debug, Default)]
pub struct InputSession;
impl InputSession {
pub fn button(&mut self, _button: auv_driver_common::MouseButton, _down: bool) -> DriverResult<()> {
Err(DriverError::unsupported("linux.portal.input"))
}
pub fn move_to(&mut self, _point: Point) -> DriverResult<()> {
Err(DriverError::unsupported("linux.portal.input"))
}
pub fn click_at(
&mut self,
_point: Point,
_button: auv_driver_common::MouseButton,
_click: Click,
_modifiers: &[i32],
) -> DriverResult<()> {
Err(DriverError::unsupported("linux.portal.input"))
}
pub fn scroll(&mut self, _scroll: Scroll) -> DriverResult<()> {
Err(DriverError::unsupported("linux.portal.input"))
}
pub fn scroll_at(&mut self, _point: Point, _scroll: Scroll) -> DriverResult<()> {
Err(DriverError::unsupported("linux.portal.input"))
}
pub fn key_press(&mut self, _keysym: i32) -> DriverResult<()> {
Err(DriverError::unsupported("linux.portal.input"))
}
pub fn key_transition(&mut self, _keysym: i32, _down: bool) -> DriverResult<()> {
Err(DriverError::unsupported("linux.portal.input"))
}
pub fn key_chord(&mut self, _modifiers: &[i32], _key: i32) -> DriverResult<()> {
Err(DriverError::unsupported("linux.portal.input"))
}
}
#[derive(Debug, Default)]
pub struct ScreenCastSession;
impl ScreenCastSession {
pub fn open_monitor(_restore_tokens: Option<&RestoreTokenStore>, _app_id: Option<&String>) -> DriverResult<Self> {
Err(DriverError::unsupported("linux.portal.screencast"))
}
}
}