denise_evdev/lib.rs
1//! Linux evdev input for Denise.
2//!
3//! Reads mice, touchscreens and keyboards straight from `/dev/input/event*`, with
4//! no display server in the way.
5//!
6//! # Testing
7//!
8//! [`translate`] and [`keymap`] are platform-independent and unit tested
9//! everywhere. That is not tidiness: multitouch slot tracking, frame batching and
10//! modifier state are the parts that break, and each one is far easier to pin down
11//! as a table of raw event codes than by dragging a finger across a panel and
12//! guessing. Only device discovery and reading are gated to Linux.
13//!
14//! # Permissions
15//!
16//! Reading `/dev/input/event*` needs membership in the `input` group, or root.
17//! Being able to read every keystroke on the machine is exactly as sensitive as it
18//! sounds, which is why the group exists.
19//!
20//! # Blocking
21//!
22//! [`InputBackend::poll`] never blocks: it drains whatever is ready and returns.
23//! A frame loop that wants to sleep should wait on [`InputBackend::raw_fds`]
24//! together with the DRM device's descriptor, so the process idles in the kernel
25//! until either input arrives or the display retires a flip — rather than spinning
26//! to ask.
27//!
28//! # Devices that arrive late
29//!
30//! The set is not fixed, so that list of descriptors is not either. A wireless
31//! mouse asleep when the panel starts has no `/dev/input/event*` node at all — the
32//! receiver enumerates, the mouse does not — and the node appears whenever
33//! somebody first moves it, which on a machine left running is measured in
34//! minutes rather than seconds. `poll` opens it then, and a loop holding a list
35//! made at startup would neither read it nor wake for it.
36//!
37//! So: ask [`InputBackend::devices_changed`] each pass, and take
38//! [`InputBackend::raw_fds`] again when it says yes. `examples/bare-linux`
39//! packages that as `Waits` and every kiosk example uses it.
40
41pub mod codes;
42pub mod keymap;
43pub mod layout;
44pub mod translate;
45
46pub use keymap::key_code;
47pub use translate::{AbsAxis, MAX_SLOTS, RawEvent, Translator};
48
49#[cfg(target_os = "linux")]
50pub mod console;
51#[cfg(target_os = "linux")]
52mod device;
53#[cfg(target_os = "linux")]
54mod error;
55
56#[cfg(target_os = "linux")]
57pub use console::{Console, ConsoleError};
58#[cfg(target_os = "linux")]
59pub use device::{Capabilities, InputBackend, InputDevice};
60#[cfg(target_os = "linux")]
61pub use error::EvdevError;
62
63/// Compiles the examples in this crate's README, so they cannot drift from the API
64/// they claim to demonstrate. Never built except under `cargo test --doc`.
65#[cfg(doctest)]
66#[doc = include_str!("../README.md")]
67struct Readme;