denise_evdev/lib.rs
1//! Linux evdev input for Denise.
2//!
3//! Reads mice, touchpads, touchscreens and keyboards straight from
4//! `/dev/input/event*`, with 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//! [`InputSource::poll`](denise::InputSource::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
41// Off Linux, some of the items the documentation above links to are compiled
42// out, so those links resolve to nothing and `cargo doc` fails. CI documents on
43// Ubuntu and never sees it; a developer on a Mac cannot avoid it. Linux stays
44// the platform that checks these links, being the one with the items to check
45// them against.
46#![cfg_attr(not(target_os = "linux"), allow(rustdoc::broken_intra_doc_links))]
47
48pub mod codes;
49pub mod keymap;
50pub mod translate;
51
52/// Keyboard layouts, re-exported from [`denise_layout`].
53///
54/// They lived here until 0.16, and a position-to-character table is no more
55/// about evdev than it is about Cocoa — an on-screen keyboard wants the same
56/// tables and should not depend on a Linux input backend to get them.
57pub use denise_layout as layout;
58
59pub use keymap::key_code;
60pub use translate::{AbsAxis, MAX_SLOTS, RawEvent, Translator};
61
62#[cfg(target_os = "linux")]
63pub mod console;
64#[cfg(target_os = "linux")]
65mod device;
66#[cfg(target_os = "linux")]
67mod error;
68
69#[cfg(target_os = "linux")]
70pub use console::{Console, ConsoleError};
71#[cfg(target_os = "linux")]
72pub use device::{Capabilities, InputBackend, InputDevice};
73#[cfg(target_os = "linux")]
74pub use error::EvdevError;
75
76/// Compiles the examples in this crate's README, so they cannot drift from the API
77/// they claim to demonstrate. Never built except under `cargo test --doc`.
78#[cfg(doctest)]
79#[doc = include_str!("../README.md")]
80struct Readme;