12 releases

new 0.2.0 Jan 17, 2025
0.1.5 Jan 16, 2025
0.0.5 Dec 19, 2024
0.0.4 Aug 17, 2024
0.0.2 Jul 18, 2024

#163 in Hardware support

Download history 7/week @ 2024-09-27 2/week @ 2024-10-04 7/week @ 2024-10-11 4/week @ 2024-11-01 2/week @ 2024-11-08 7/week @ 2024-12-06 74/week @ 2024-12-13 52/week @ 2024-12-20 1/week @ 2025-01-03 262/week @ 2025-01-10

384 downloads per month
Used in saddle

Apache-2.0

300KB
3K SLoC

Colpetto

Colpetto is a modern Rust library that provides asynchronous bindings for libinput, enabling efficient handling of input device events on Linux systems. Built on tokio, it offers a stream-based API that seamlessly integrates with async applications while maintaining low latency and efficient resource usage for real-time operations.

Key Features

Colpetto transforms libinput's traditional callback-based interface into an ergonomic Rust API with:

  • Stream-based event handling powered by tokio
  • Low-overhead event polling optimized for performance
  • Flexible logging system with built-in basic loggers

Examples

Here's a basic example demonstrating event handling using rustix:

use colpetto::{event::AsRawEvent, Libinput, Result};
use rustix::{
    fd::{FromRawFd, IntoRawFd, OwnedFd},
    fs::{open, Mode, OFlags},
    io::Errno,
};
use tokio_stream::StreamExt;

#[tokio::main]
async fn main() -> Result<()> {
    let mut libinput = Libinput::new(
        |path, flags| {
            open(path, OFlags::from_bits_retain(flags as u32), Mode::empty())
                .map(IntoRawFd::into_raw_fd)
                .map_err(Errno::raw_os_error)
        },
        |fd| drop(unsafe { OwnedFd::from_raw_fd(fd) }),
    )?;
    
    libinput.assign_seat(c"seat0")?;
    let mut stream = libinput.event_stream()?;

    while let Some(event) = stream.try_next().await? {
        println!(
            "Got \"{}\" event from \"{}\"",
            event.event_type(),
            event.device().name().to_string_lossy()
        )
    }

    Ok(())
}

For more examples, check out the examples directory:

  • Simple: Basic event handling demonstration
  • Print Keys: Advanced example with custom logging and keyboard event handling

Comparison with input-rs

While input-rs is an established alternative, Colpetto takes a different approach in several key areas:

Interface Design

Colpetto uses direct function passing for device management, while input-rs employs a trait-based approach:

// Colpetto: Function-based approach with closure support
let mut libinput = Libinput::new(
    |path, flags| {  // Open function
        open(path, OFlags::from_bits_retain(flags as u32), Mode::empty())
            .map(IntoRawFd::into_raw_fd)
            .map_err(Errno::raw_os_error)
    },
    |fd| drop(unsafe { OwnedFd::from_raw_fd(fd) })  // Close function
)?;

// input-rs: Trait-based approach
struct Interface;

impl LibinputInterface for Interface {
    fn open_restricted(&mut self, path: &Path, flags: i32) -> Result<OwnedFd, i32> {
        open(path, OFlags::from_bits_retain(flags as u32), Mode::empty())
            .map_err(Errno::raw_os_error)
    }
    fn close_restricted(&mut self, fd: OwnedFd) {
        drop(fd);
    }
}
let mut input = Libinput::new_with_udev(Interface);

Some key Advantages

  • Native tokio integration for async/await support
  • Stream-based event handling via event_stream()
  • Safe handling of non-UTF8 strings using CStr instead of implicit panics
  • Comprehensive event type safety through more exhaustive enum matching
  • More robust context lifetime management

License

This project is licensed under the Apache-2.0 License. For more information, please see the LICENSE file.

Dependencies

~3–11MB
~120K SLoC