Add support for key autorepeat (EV_REP - REP_DELAY and REP_PERIOD)

This commit is contained in:
Jan Trefil 2023-12-02 14:22:46 +01:00
parent 1c148cf3a3
commit 607e1fb14c
7 changed files with 119 additions and 3 deletions

View file

@ -123,6 +123,8 @@ pub async fn run(
rel, rel,
abs, abs,
keys, keys,
delay,
period,
} => { } => {
let entry = writers.entry(id); let entry = writers.entry(id);
if let Entry::Occupied(_) = entry { if let Entry::Occupied(_) = entry {
@ -141,6 +143,8 @@ pub async fn run(
.rel(rel)? .rel(rel)?
.abs(abs)? .abs(abs)?
.key(keys)? .key(keys)?
.delay(delay)?
.period(period)?
.build() .build()
.await .await
} }

View file

@ -1,6 +1,6 @@
mod caps; mod caps;
pub use caps::{AbsCaps, KeyCaps, RelCaps}; pub use caps::{AbsCaps, KeyCaps, RelCaps, Repeat};
use crate::abs::{AbsAxis, AbsEvent, ToolType}; use crate::abs::{AbsAxis, AbsEvent, ToolType};
use crate::convert::Convert; use crate::convert::Convert;
@ -137,6 +137,10 @@ impl Interceptor {
KeyCaps::new(self) KeyCaps::new(self)
} }
pub fn repeat(&self) -> Repeat {
Repeat::new(self)
}
async fn read_raw(&mut self) -> Result<(u16, u16, i32), Error> { async fn read_raw(&mut self) -> Result<(u16, u16, i32), Error> {
let file = self.evdev.file().unwrap(); let file = self.evdev.file().unwrap();
@ -234,7 +238,10 @@ impl Interceptor {
if ret < 0 { if ret < 0 {
// We do not use ErrorKind::ResourceBusy because it is a nightly-only API. // We do not use ErrorKind::ResourceBusy because it is a nightly-only API.
let err = if ret == -libc::EBUSY { let err = if ret == -libc::EBUSY {
tracing::info!("Ignored {:?} because it is busy and can not be grabbed", path); tracing::info!(
"Ignored {:?} because it is busy and can not be grabbed",
path
);
OpenError::NotAppliable OpenError::NotAppliable
} else { } else {
Error::from_raw_os_error(-ret).into() Error::from_raw_os_error(-ret).into()

View file

@ -155,3 +155,51 @@ impl Iterator for KeyCaps<'_> {
None None
} }
} }
pub struct Repeat {
pub delay: Option<i32>,
pub period: Option<i32>,
}
impl Repeat {
pub(super) fn new(interceptor: &Interceptor) -> Self {
let has = unsafe {
glue::libevdev_has_event_code(interceptor.evdev.as_ptr(), glue::EV_REP, glue::REP_DELAY)
== 1
};
let delay = if has {
Some(unsafe {
glue::libevdev_get_event_value(
interceptor.evdev.as_ptr(),
glue::EV_REP,
glue::REP_DELAY,
)
})
} else {
None
};
let has = unsafe {
glue::libevdev_has_event_code(
interceptor.evdev.as_ptr(),
glue::EV_REP,
glue::REP_PERIOD,
) == 1
};
let period = if has {
Some(unsafe {
glue::libevdev_get_event_value(
interceptor.evdev.as_ptr(),
glue::EV_REP,
glue::REP_PERIOD,
)
})
} else {
None
};
Self { delay, period }
}
}

View file

@ -1,3 +1,5 @@
use libc::c_int;
use crate::abs::{AbsAxis, AbsEvent, AbsInfo}; use crate::abs::{AbsAxis, AbsEvent, AbsInfo};
use crate::convert::Convert; use crate::convert::Convert;
use crate::evdev::Evdev; use crate::evdev::Evdev;
@ -236,6 +238,50 @@ impl WriterBuilder {
Ok(self) Ok(self)
} }
pub fn delay(self, value: Option<i32>) -> Result<Self, Error> {
let value: c_int = match value {
Some(value) => value,
None => return Ok(self),
};
let ret = unsafe {
glue::libevdev_enable_event_code(
self.evdev.as_ptr(),
glue::EV_REP,
glue::REP_DELAY,
&value as *const _ as *const _,
)
};
if ret < 0 {
return Err(Error::from_raw_os_error(-ret));
}
Ok(self)
}
pub fn period(self, value: Option<i32>) -> Result<Self, Error> {
let value: c_int = match value {
Some(value) => value,
None => return Ok(self),
};
let ret = unsafe {
glue::libevdev_enable_event_code(
self.evdev.as_ptr(),
glue::EV_REP,
glue::REP_PERIOD,
&value as *const _ as *const _,
)
};
if ret < 0 {
return Err(Error::from_raw_os_error(-ret));
}
Ok(self)
}
pub async fn build(self) -> Result<Writer, Error> { pub async fn build(self) -> Result<Writer, Error> {
Writer::from_evdev(&self.evdev).await Writer::from_evdev(&self.evdev).await
} }

View file

@ -36,6 +36,8 @@ pub enum Update {
rel: HashSet<RelAxis>, rel: HashSet<RelAxis>,
abs: HashMap<AbsAxis, AbsInfo>, abs: HashMap<AbsAxis, AbsInfo>,
keys: HashSet<Key>, keys: HashSet<Key>,
delay: Option<i32>,
period: Option<i32>,
}, },
DestroyDevice { DestroyDevice {
id: usize, id: usize,

View file

@ -8,7 +8,7 @@ use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
pub struct Version(u16); pub struct Version(u16);
impl Version { impl Version {
pub const CURRENT: Self = Self(4); pub const CURRENT: Self = Self(5);
} }
impl Display for Version { impl Display for Version {

View file

@ -79,6 +79,8 @@ pub async fn run(
rel: device.rel.clone(), rel: device.rel.clone(),
abs: device.abs.clone(), abs: device.abs.clone(),
keys: device.keys.clone(), keys: device.keys.clone(),
delay: device.delay,
period: device.period,
}) })
.collect(); .collect();
@ -109,6 +111,7 @@ pub async fn run(
let rel = interceptor.rel().collect::<HashSet<_>>(); let rel = interceptor.rel().collect::<HashSet<_>>();
let abs = interceptor.abs().collect::<HashMap<_,_>>(); let abs = interceptor.abs().collect::<HashMap<_,_>>();
let keys = interceptor.key().collect::<HashSet<_>>(); let keys = interceptor.key().collect::<HashSet<_>>();
let repeat = interceptor.repeat();
for (_, (sender, _)) in &clients { for (_, (sender, _)) in &clients {
let update = Update::CreateDevice { let update = Update::CreateDevice {
@ -120,6 +123,8 @@ pub async fn run(
rel: rel.clone(), rel: rel.clone(),
abs: abs.clone(), abs: abs.clone(),
keys: keys.clone(), keys: keys.clone(),
delay: repeat.delay,
period: repeat.period,
}; };
let _ = sender.send(update).await; let _ = sender.send(update).await;
@ -134,6 +139,8 @@ pub async fn run(
rel, rel,
abs, abs,
keys, keys,
delay: repeat.delay,
period: repeat.period,
sender: interceptor_sender, sender: interceptor_sender,
}); });
@ -278,6 +285,8 @@ struct Device {
rel: HashSet<RelAxis>, rel: HashSet<RelAxis>,
abs: HashMap<AbsAxis, AbsInfo>, abs: HashMap<AbsAxis, AbsInfo>,
keys: HashSet<Key>, keys: HashSet<Key>,
delay: Option<i32>,
period: Option<i32>,
sender: Sender<Event>, sender: Sender<Event>,
} }