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

View file

@ -1,6 +1,6 @@
mod caps;
pub use caps::{AbsCaps, KeyCaps, RelCaps};
pub use caps::{AbsCaps, KeyCaps, RelCaps, Repeat};
use crate::abs::{AbsAxis, AbsEvent, ToolType};
use crate::convert::Convert;
@ -137,6 +137,10 @@ impl Interceptor {
KeyCaps::new(self)
}
pub fn repeat(&self) -> Repeat {
Repeat::new(self)
}
async fn read_raw(&mut self) -> Result<(u16, u16, i32), Error> {
let file = self.evdev.file().unwrap();
@ -234,7 +238,10 @@ impl Interceptor {
if ret < 0 {
// We do not use ErrorKind::ResourceBusy because it is a nightly-only API.
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
} else {
Error::from_raw_os_error(-ret).into()

View file

@ -155,3 +155,51 @@ impl Iterator for KeyCaps<'_> {
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::convert::Convert;
use crate::evdev::Evdev;
@ -236,6 +238,50 @@ impl WriterBuilder {
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> {
Writer::from_evdev(&self.evdev).await
}

View file

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

View file

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

View file

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