okey-cli 0.1.2

An advanced, easy-to-use key remapper for Linux
Documentation
use anyhow::Result;
use evdev::{Device, InputEvent, uinput::VirtualDevice};
use nix::sys::epoll::{Epoll, EpollCreateFlags, EpollEvent, EpollFlags};

pub trait EventProxy {
    fn emit(&mut self, events: &[InputEvent]) -> Result<()>;
    fn wait(&mut self, timeout: u16) -> Result<()>;
}

#[derive(Debug)]
pub struct InputProxy {
    epoll: Epoll,
    event_buffer: [EpollEvent; 1],
    virtual_device: VirtualDevice,
}

impl InputProxy {
    pub fn try_from_device(device: &Device) -> Result<Self> {
        let name = format!("{} (virtual)", device.name().unwrap_or("Unknown device"));
        let virtual_device = VirtualDevice::builder()?
            .name(&name)
            .with_keys(device.supported_keys().unwrap_or_default())?
            .build()?;

        let epoll = Epoll::new(EpollCreateFlags::EPOLL_CLOEXEC)?;
        let event = EpollEvent::new(EpollFlags::EPOLLIN, 0);
        let event_buffer = [EpollEvent::empty(); 1];

        epoll.add(device, event)?;

        Ok(Self {
            epoll,
            event_buffer,
            virtual_device,
        })
    }
}

impl EventProxy for InputProxy {
    fn emit(&mut self, events: &[InputEvent]) -> Result<()> {
        self.virtual_device.emit(events)?;
        Ok(())
    }

    fn wait(&mut self, timeout: u16) -> Result<()> {
        self.epoll.wait(&mut self.event_buffer, timeout)?;
        Ok(())
    }
}