pub(crate) mod codes;
#[cfg(any(test, feature = "serde"))]
mod serde;
use std::fmt;
use std::ops::Deref;
use std::time::{Duration, SystemTime};
use crate::ff::{self, EffectId};
use crate::raw::input::input_event;
pub use codes::{Abs, EventType, Key, Led, Misc, Rel, Repeat, Sound, Switch, Syn, UinputCode};
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct InputEvent(input_event);
impl InputEvent {
#[inline]
pub const fn new(ty: EventType, raw_code: u16, raw_value: i32) -> Self {
Self(input_event {
time: libc::timeval {
tv_sec: 0,
tv_usec: 0,
},
type_: ty.0,
code: raw_code,
value: raw_value,
})
}
#[inline]
pub const fn zeroed() -> Self {
Self(input_event {
time: libc::timeval {
tv_sec: 0,
tv_usec: 0,
},
type_: 0,
code: 0,
value: 0,
})
}
pub fn with_time(mut self, time: SystemTime) -> Self {
let dur = if time >= SystemTime::UNIX_EPOCH {
time.duration_since(SystemTime::UNIX_EPOCH).unwrap()
} else {
SystemTime::UNIX_EPOCH.duration_since(time).unwrap()
};
let sign = if time >= SystemTime::UNIX_EPOCH {
1
} else {
-1
};
let sec = dur.as_secs();
let usec = dur.subsec_micros();
self.0.time.tv_sec = sec.try_into().unwrap();
self.0.time.tv_sec *= sign;
self.0.time.tv_usec = usec.try_into().unwrap();
self
}
pub fn time(&self) -> SystemTime {
match self.try_time() {
Some(time) => time,
None => {
log::warn!(
"`input_event` timestamp out of range of `SystemTime`: tv_sec={} tv_usec={}",
self.0.time.tv_sec,
self.0.time.tv_usec,
);
SystemTime::UNIX_EPOCH
}
}
}
fn try_time(&self) -> Option<SystemTime> {
let sec = self.0.time.tv_sec;
let usec = self.0.time.tv_usec.clamp(0, 999_999);
let dur = Duration::new(
sec.unsigned_abs() as u64,
(usec * 1000) as u32, );
if sec >= 0 {
SystemTime::UNIX_EPOCH.checked_add(dur)
} else {
SystemTime::UNIX_EPOCH.checked_sub(dur)
}
}
#[inline]
pub fn kind(&self) -> EventKind {
match self.event_type() {
EventType::SYN => SynEvent(*self).into(),
EventType::KEY => KeyEvent(*self).into(),
EventType::REL => RelEvent(*self).into(),
EventType::ABS => AbsEvent(*self).into(),
EventType::SW => SwitchEvent(*self).into(),
EventType::MSC => MiscEvent(*self).into(),
EventType::LED => LedEvent(*self).into(),
EventType::REP => RepeatEvent(*self).into(),
EventType::SND => SoundEvent(*self).into(),
EventType::UINPUT => UinputEvent(*self).into(),
EventType::FF => ForceFeedbackEvent(*self).into(),
_ => EventKind::Other(*self),
}
}
#[inline]
pub fn event_type(&self) -> EventType {
EventType(self.0.type_)
}
#[inline]
pub fn raw_code(&self) -> u16 {
self.0.code
}
#[inline]
pub fn raw_value(&self) -> i32 {
self.0.value
}
}
impl fmt::Debug for InputEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind() {
EventKind::Other(_) => f
.debug_struct("InputEvent")
.field("time", &self.time())
.field("type", &self.event_type())
.field("code", &self.raw_code())
.field("value", &self.raw_value())
.finish(),
kind => kind.fmt(f),
}
}
}
macro_rules! event_wrappers {
( $(
$(#[$attr:meta])*
pub struct $name:ident in $variant:ident;
)* ) => {
$(
$( #[$attr] )*
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct $name(InputEvent);
impl From<$name> for EventKind {
#[inline]
fn from(value: $name) -> Self {
Self::$variant(value)
}
}
impl From<$name> for InputEvent {
#[inline]
fn from(value: $name) -> Self {
value.0
}
}
impl Deref for $name {
type Target = InputEvent;
#[inline]
fn deref(&self) -> &InputEvent {
&self.0
}
}
)*
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum EventKind {
$(
$( #[$attr] )*
$variant($name),
)*
#[non_exhaustive] Other(InputEvent),
}
impl From<EventKind> for InputEvent {
#[inline]
fn from(kind: EventKind) -> InputEvent {
match kind {
$(
EventKind::$variant(it) => *it,
)*
EventKind::Other(ev) => ev,
}
}
}
};
}
event_wrappers! {
pub struct SynEvent in Syn;
pub struct KeyEvent in Key;
pub struct RelEvent in Rel;
pub struct AbsEvent in Abs;
pub struct SwitchEvent in Switch;
pub struct MiscEvent in Misc;
pub struct LedEvent in Led;
pub struct RepeatEvent in Repeat;
pub struct SoundEvent in Sound;
pub struct UinputEvent in Uinput;
pub struct ForceFeedbackEvent in ForceFeedback;
}
impl SynEvent {
#[inline]
pub fn new(syn: Syn) -> Self {
Self(InputEvent::new(EventType::SYN, syn.0, 0))
}
#[inline]
pub fn syn(&self) -> Syn {
Syn(self.raw_code())
}
}
impl fmt::Debug for SynEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SynEvent")
.field("time", &self.time())
.field("syn", &self.syn())
.field("value", &self.raw_value())
.finish()
}
}
impl From<Syn> for SynEvent {
#[inline]
fn from(syn: Syn) -> Self {
Self::new(syn)
}
}
impl From<Syn> for EventKind {
#[inline]
fn from(value: Syn) -> Self {
Self::Syn(value.into())
}
}
impl From<Syn> for InputEvent {
#[inline]
fn from(value: Syn) -> Self {
SynEvent::new(value).into()
}
}
impl KeyEvent {
#[inline]
pub fn new(key: Key, state: KeyState) -> Self {
Self(InputEvent::new(EventType::KEY, key.0, state.0))
}
#[inline]
pub fn key(&self) -> Key {
Key(self.raw_code())
}
#[inline]
pub fn state(&self) -> KeyState {
KeyState(self.raw_value())
}
}
impl fmt::Debug for KeyEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("KeyEvent")
.field("time", &self.time())
.field("key", &self.key())
.field("state", &self.state())
.finish()
}
}
ffi_enum! {
pub enum KeyState: i32 {
RELEASED = 0,
PRESSED = 1,
REPEAT = 2,
}
}
impl fmt::Debug for KeyState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.variant_name() {
Some(name) => f.write_str(name),
None => write!(f, "KeyState({:#?})", self.0),
}
}
}
impl RelEvent {
#[inline]
pub fn new(rel: Rel, value: i32) -> Self {
Self(InputEvent::new(EventType::REL, rel.0, value))
}
#[inline]
pub fn rel(&self) -> Rel {
Rel(self.raw_code())
}
#[inline]
pub fn value(&self) -> i32 {
self.raw_value()
}
}
impl fmt::Debug for RelEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RelEvent")
.field("time", &self.time())
.field("rel", &self.rel())
.field("value", &self.value())
.finish()
}
}
impl AbsEvent {
#[inline]
pub fn new(abs: Abs, value: i32) -> Self {
Self(InputEvent::new(EventType::ABS, abs.0, value))
}
#[inline]
pub fn abs(&self) -> Abs {
Abs(self.raw_code())
}
#[inline]
pub fn value(&self) -> i32 {
self.raw_value()
}
}
impl fmt::Debug for AbsEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AbsEvent")
.field("time", &self.time())
.field("abs", &self.abs())
.field("value", &self.value())
.finish()
}
}
impl SwitchEvent {
#[inline]
pub fn new(switch: Switch, on: bool) -> Self {
Self(InputEvent::new(
EventType::SW,
switch.0,
if on { 1 } else { 0 },
))
}
#[inline]
pub fn switch(&self) -> Switch {
Switch(self.raw_code())
}
#[inline]
pub fn is_pressed(&self) -> bool {
self.raw_value() != 0
}
}
impl fmt::Debug for SwitchEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SwitchEvent")
.field("time", &self.time())
.field("switch", &self.switch())
.field("pressed", &self.is_pressed())
.finish()
}
}
impl MiscEvent {
#[inline]
pub fn new(misc: Misc, value: i32) -> Self {
Self(InputEvent::new(EventType::MSC, misc.0, value))
}
#[inline]
pub fn misc(&self) -> Misc {
Misc(self.raw_code())
}
}
impl fmt::Debug for MiscEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MiscEvent")
.field("time", &self.time())
.field("misc", &self.misc())
.field("value", &self.raw_value())
.finish()
}
}
impl LedEvent {
#[inline]
pub fn new(led: Led, on: bool) -> Self {
Self(InputEvent::new(
EventType::LED,
led.0,
if on { 1 } else { 0 },
))
}
#[inline]
pub fn led(&self) -> Led {
Led(self.raw_code())
}
#[inline]
pub fn is_on(&self) -> bool {
!self.is_off()
}
#[inline]
pub fn is_off(&self) -> bool {
self.0.raw_value() == 0
}
}
impl fmt::Debug for LedEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("LedEvent")
.field("time", &self.time())
.field("led", &self.led())
.field("state", &self.is_on())
.finish()
}
}
impl RepeatEvent {
#[inline]
pub fn new(repeat: Repeat, value: u32) -> Self {
Self(InputEvent::new(EventType::REP, repeat.0, value as i32))
}
#[inline]
pub fn repeat(&self) -> Repeat {
Repeat(self.raw_code())
}
#[inline]
pub fn value(&self) -> u32 {
self.raw_value() as u32
}
}
impl fmt::Debug for RepeatEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RepeatEvent")
.field("time", &self.time())
.field("repeat", &self.repeat())
.field("value", &self.raw_value())
.finish()
}
}
impl SoundEvent {
#[inline]
pub fn new(sound: Sound, playing: bool) -> Self {
Self(InputEvent::new(
EventType::SND,
sound.0,
if playing { 1 } else { 0 },
))
}
#[inline]
pub fn sound(&self) -> Sound {
Sound(self.raw_code())
}
#[inline]
pub fn is_playing(&self) -> bool {
self.raw_value() != 0
}
}
impl fmt::Debug for SoundEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SoundEvent")
.field("time", &self.time())
.field("sound", &self.sound())
.field("value", &self.raw_value())
.finish()
}
}
impl UinputEvent {
#[inline]
pub fn code(&self) -> UinputCode {
UinputCode(self.raw_code())
}
}
impl fmt::Debug for UinputEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("UinputEvent")
.field("time", &self.time())
.field("code", &self.code())
.field("value", &self.raw_value())
.finish()
}
}
impl ForceFeedbackEvent {
#[inline]
pub fn control_effect(effect: EffectId, active: bool) -> Self {
Self(InputEvent::new(
EventType::FF,
effect.0 as u16,
if active { 1 } else { 0 },
))
}
#[inline]
pub fn control_gain(gain: u16) -> Self {
Self(InputEvent::new(
EventType::FF,
ff::Feature::GAIN.0,
gain.into(),
))
}
#[inline]
pub fn control_autocenter(autocenter: u16) -> Self {
Self(InputEvent::new(
EventType::FF,
ff::Feature::AUTOCENTER.0,
autocenter.into(),
))
}
#[inline]
pub fn code(&self) -> Option<ForceFeedbackCode> {
const FF_GAIN: u16 = ff::Feature::GAIN.0;
const FF_AUTOCENTER: u16 = ff::Feature::AUTOCENTER.0;
match self.raw_code() {
id if id < FF_GAIN => Some(ForceFeedbackCode::ControlEffect(EffectId(id as i16))),
FF_GAIN => Some(ForceFeedbackCode::SetGain),
FF_AUTOCENTER => Some(ForceFeedbackCode::SetAutocenter),
_ => None,
}
}
}
impl fmt::Debug for ForceFeedbackEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ForceFeedbackEvent")
.field("time", &self.time())
.field("code", &self.code())
.field("value", &self.raw_value())
.finish()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ForceFeedbackCode {
ControlEffect(EffectId),
SetGain,
SetAutocenter,
}
ffi_enum! {
pub enum MtToolType: i32 {
FINGER = 0x00,
PEN = 0x01,
PALM = 0x02,
DIAL = 0x0a,
}
}
impl fmt::Debug for MtToolType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.variant_name() {
Some(name) => write!(f, "MT_TOOL_{name}"),
None => write!(f, "MtToolType({:#?})", self.0),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn timestamps() {
const EV: InputEvent = InputEvent::zeroed();
let epoch = EV.with_time(SystemTime::UNIX_EPOCH);
assert_eq!(epoch.0.time.tv_sec, 0);
assert_eq!(epoch.0.time.tv_usec, 0);
let mut negative_micros = EV;
negative_micros.0.time.tv_usec = -1;
assert_eq!(
negative_micros.time(),
SystemTime::UNIX_EPOCH,
"should saturate to `UNIX_EPOCH`",
);
assert_eq!(
negative_micros.time(),
EV.with_time(SystemTime::UNIX_EPOCH).time(),
);
let mut before_epoch = EV;
before_epoch.0.time.tv_sec = -1;
assert_eq!(
before_epoch.time(),
SystemTime::UNIX_EPOCH - Duration::from_secs(1),
);
assert_eq!(
before_epoch.time(),
EV.with_time(SystemTime::UNIX_EPOCH - Duration::from_secs(1))
.time()
);
let mut after_epoch = EV;
after_epoch.0.time.tv_sec = 1_000_000;
assert_eq!(
after_epoch.time(),
SystemTime::UNIX_EPOCH + Duration::from_secs(1_000_000),
);
assert_eq!(
after_epoch.time(),
EV.with_time(SystemTime::UNIX_EPOCH + Duration::from_secs(1_000_000))
.time()
);
}
}