Skip to main content

Keyboard

Struct Keyboard 

Source
pub struct Keyboard { /* private fields */ }
Available on crate feature xkb only.
Expand description

A keymap and the state of the keys pressed against it.

One per seat, not one per device: a user typing on two keyboards is holding Shift on one and pressing a letter on the other, and xkb has to see both.

Implementations§

Source§

impl Keyboard

Source

pub fn from_names(names: &KeymapNames) -> Result<Self, InputError>

Compile a keymap from RMLVO names.

§Errors

InputError::Keymap if the names do not compile – a layout that is not installed, an option that does not exist.

Examples found in repository?
examples/input.rs (line 36)
28fn main() {
29    let mut seat = match Seat::open(&SeatOptions::default()) {
30        Ok(seat) => seat,
31        Err(error) => {
32            eprintln!("{error}");
33            std::process::exit(1);
34        }
35    };
36    let mut keyboard = Keyboard::from_names(&KeymapNames::default()).expect("keymap");
37    let mut repeater = KeyRepeater::new(RepeatConfig::default()).expect("timer");
38
39    let started = Instant::now();
40    let mut events = Vec::new();
41    let mut repeats: Vec<KeyEvent> = Vec::new();
42    let mut leds = keyboard.leds();
43
44    loop {
45        {
46            let seat_fd = seat.as_fd();
47            let timer_fd = repeater.fd();
48            let mut fds = [
49                PollFd::new(&seat_fd, PollFlags::IN),
50                PollFd::new(&timer_fd, PollFlags::IN),
51            ];
52            let timeout = Duration::from_secs(30).try_into().expect("timeout");
53            if poll(&mut fds, Some(&timeout)).expect("poll") == 0 {
54                println!("nothing for thirty seconds");
55                return;
56            }
57        }
58
59        let now = u32::try_from(started.elapsed().as_millis()).unwrap_or(u32::MAX);
60
61        events.clear();
62        seat.dispatch(&mut events).expect("dispatch");
63        for event in &mut events {
64            match event {
65                InputEvent::Key(key) => {
66                    keyboard.process_key(key);
67                    repeater.on_key(key, keyboard.should_repeat(key.key));
68                    if report(key) {
69                        return;
70                    }
71                }
72                other => println!("{other:?}"),
73            }
74        }
75
76        repeats.clear();
77        repeater.dispatch(now, &mut repeats).expect("repeat");
78        for key in &mut repeats {
79            // Resolved, not replayed: a Shift pressed since the key went down
80            // changes what this types.
81            keyboard.resolve(key);
82            report(key);
83        }
84
85        let current = keyboard.leds();
86        if current != leds {
87            seat.set_leds(current);
88            leds = current;
89        }
90    }
91}
Source

pub fn from_file(path: &Path) -> Result<Self, InputError>

Compile a keymap from a file.

§Errors

InputError::Io if the file cannot be read, InputError::Keymap if it does not compile.

Source

pub fn from_string(keymap: &str) -> Result<Self, InputError>

Compile a keymap from text already in hand.

For a keymap that arrived over a socket or through an mmap and never touched a filesystem.

§Errors

InputError::Keymap if it does not compile.

Source

pub fn reload(&mut self, names: &KeymapNames) -> Result<(), InputError>

Swap in a keymap compiled from different names.

Keys still held are replayed onto the new state, and the lock latch is carried over, so a layout change mid-keystroke does not strand a modifier down or turn Caps Lock off underneath the user.

The current keymap is left alone if the new names do not compile.

§Errors

InputError::Keymap, as Keyboard::from_names.

Source

pub fn resolve(&self, event: &mut KeyEvent)

Fill in what a key resolves to, without touching the keyboard state.

This is what a repeat wants: the same physical key, re-read against whatever modifiers are held now, so pressing Shift partway through a held key changes what the next repeat types.

Examples found in repository?
examples/input.rs (line 81)
28fn main() {
29    let mut seat = match Seat::open(&SeatOptions::default()) {
30        Ok(seat) => seat,
31        Err(error) => {
32            eprintln!("{error}");
33            std::process::exit(1);
34        }
35    };
36    let mut keyboard = Keyboard::from_names(&KeymapNames::default()).expect("keymap");
37    let mut repeater = KeyRepeater::new(RepeatConfig::default()).expect("timer");
38
39    let started = Instant::now();
40    let mut events = Vec::new();
41    let mut repeats: Vec<KeyEvent> = Vec::new();
42    let mut leds = keyboard.leds();
43
44    loop {
45        {
46            let seat_fd = seat.as_fd();
47            let timer_fd = repeater.fd();
48            let mut fds = [
49                PollFd::new(&seat_fd, PollFlags::IN),
50                PollFd::new(&timer_fd, PollFlags::IN),
51            ];
52            let timeout = Duration::from_secs(30).try_into().expect("timeout");
53            if poll(&mut fds, Some(&timeout)).expect("poll") == 0 {
54                println!("nothing for thirty seconds");
55                return;
56            }
57        }
58
59        let now = u32::try_from(started.elapsed().as_millis()).unwrap_or(u32::MAX);
60
61        events.clear();
62        seat.dispatch(&mut events).expect("dispatch");
63        for event in &mut events {
64            match event {
65                InputEvent::Key(key) => {
66                    keyboard.process_key(key);
67                    repeater.on_key(key, keyboard.should_repeat(key.key));
68                    if report(key) {
69                        return;
70                    }
71                }
72                other => println!("{other:?}"),
73            }
74        }
75
76        repeats.clear();
77        repeater.dispatch(now, &mut repeats).expect("repeat");
78        for key in &mut repeats {
79            // Resolved, not replayed: a Shift pressed since the key went down
80            // changes what this types.
81            keyboard.resolve(key);
82            report(key);
83        }
84
85        let current = keyboard.leds();
86        if current != leds {
87            seat.set_leds(current);
88            leds = current;
89        }
90    }
91}
Source

pub fn process_key(&mut self, event: &mut KeyEvent)

Resolve a key event and fold it into the keyboard state.

Resolution happens before the state update, which is the order xkbcommon documents: a key’s own press must not change what that press produces. With a latching modifier – a sticky Shift, a dead key – the press being resolved is the one that consumes the latch, so reading afterward reads a state the user has already left. The reference resolves first too (keyboard.cpp); see the module tests.

A repeat – KeyEvent::repeat, as a key repeater synthesizes it – is resolved and nothing more, as the reference treats it: feeding xkb another press of a key it already holds is mutating the state from a read.

Examples found in repository?
examples/input.rs (line 66)
28fn main() {
29    let mut seat = match Seat::open(&SeatOptions::default()) {
30        Ok(seat) => seat,
31        Err(error) => {
32            eprintln!("{error}");
33            std::process::exit(1);
34        }
35    };
36    let mut keyboard = Keyboard::from_names(&KeymapNames::default()).expect("keymap");
37    let mut repeater = KeyRepeater::new(RepeatConfig::default()).expect("timer");
38
39    let started = Instant::now();
40    let mut events = Vec::new();
41    let mut repeats: Vec<KeyEvent> = Vec::new();
42    let mut leds = keyboard.leds();
43
44    loop {
45        {
46            let seat_fd = seat.as_fd();
47            let timer_fd = repeater.fd();
48            let mut fds = [
49                PollFd::new(&seat_fd, PollFlags::IN),
50                PollFd::new(&timer_fd, PollFlags::IN),
51            ];
52            let timeout = Duration::from_secs(30).try_into().expect("timeout");
53            if poll(&mut fds, Some(&timeout)).expect("poll") == 0 {
54                println!("nothing for thirty seconds");
55                return;
56            }
57        }
58
59        let now = u32::try_from(started.elapsed().as_millis()).unwrap_or(u32::MAX);
60
61        events.clear();
62        seat.dispatch(&mut events).expect("dispatch");
63        for event in &mut events {
64            match event {
65                InputEvent::Key(key) => {
66                    keyboard.process_key(key);
67                    repeater.on_key(key, keyboard.should_repeat(key.key));
68                    if report(key) {
69                        return;
70                    }
71                }
72                other => println!("{other:?}"),
73            }
74        }
75
76        repeats.clear();
77        repeater.dispatch(now, &mut repeats).expect("repeat");
78        for key in &mut repeats {
79            // Resolved, not replayed: a Shift pressed since the key went down
80            // changes what this types.
81            keyboard.resolve(key);
82            report(key);
83        }
84
85        let current = keyboard.leds();
86        if current != leds {
87            seat.set_leds(current);
88            leds = current;
89        }
90    }
91}
Source

pub fn release_all(&mut self)

Release everything held, keeping the lock state.

For a session coming back from a VT switch, which is a thing the user does by holding Ctrl and Alt. Those keys come up while the device is revoked, and whether their releases survive the round trip is libinput’s business rather than something to depend on – so the state is squared away on resume instead. Getting it wrong the other way is a session where every keystroke is a Ctrl chord until the user presses and releases Ctrl again.

Locks survive: Caps Lock is not something the user let go of.

Source

pub fn should_repeat(&self, key: u32) -> bool

Whether the keymap says this key auto-repeats.

False for modifiers and lock keys, true for letters, digits, arrows and function keys – and it is the keymap’s answer, not a guess.

Examples found in repository?
examples/input.rs (line 67)
28fn main() {
29    let mut seat = match Seat::open(&SeatOptions::default()) {
30        Ok(seat) => seat,
31        Err(error) => {
32            eprintln!("{error}");
33            std::process::exit(1);
34        }
35    };
36    let mut keyboard = Keyboard::from_names(&KeymapNames::default()).expect("keymap");
37    let mut repeater = KeyRepeater::new(RepeatConfig::default()).expect("timer");
38
39    let started = Instant::now();
40    let mut events = Vec::new();
41    let mut repeats: Vec<KeyEvent> = Vec::new();
42    let mut leds = keyboard.leds();
43
44    loop {
45        {
46            let seat_fd = seat.as_fd();
47            let timer_fd = repeater.fd();
48            let mut fds = [
49                PollFd::new(&seat_fd, PollFlags::IN),
50                PollFd::new(&timer_fd, PollFlags::IN),
51            ];
52            let timeout = Duration::from_secs(30).try_into().expect("timeout");
53            if poll(&mut fds, Some(&timeout)).expect("poll") == 0 {
54                println!("nothing for thirty seconds");
55                return;
56            }
57        }
58
59        let now = u32::try_from(started.elapsed().as_millis()).unwrap_or(u32::MAX);
60
61        events.clear();
62        seat.dispatch(&mut events).expect("dispatch");
63        for event in &mut events {
64            match event {
65                InputEvent::Key(key) => {
66                    keyboard.process_key(key);
67                    repeater.on_key(key, keyboard.should_repeat(key.key));
68                    if report(key) {
69                        return;
70                    }
71                }
72                other => println!("{other:?}"),
73            }
74        }
75
76        repeats.clear();
77        repeater.dispatch(now, &mut repeats).expect("repeat");
78        for key in &mut repeats {
79            // Resolved, not replayed: a Shift pressed since the key went down
80            // changes what this types.
81            keyboard.resolve(key);
82            report(key);
83        }
84
85        let current = keyboard.leds();
86        if current != leds {
87            seat.set_leds(current);
88            leds = current;
89        }
90    }
91}
Source

pub fn modifiers(&self) -> Modifiers

Which modifiers are in effect.

Source

pub fn leds(&self) -> Leds

The lock state.

Compare two of these to spot a transition, then push the new one to the devices so the physical lights follow.

Examples found in repository?
examples/input.rs (line 42)
28fn main() {
29    let mut seat = match Seat::open(&SeatOptions::default()) {
30        Ok(seat) => seat,
31        Err(error) => {
32            eprintln!("{error}");
33            std::process::exit(1);
34        }
35    };
36    let mut keyboard = Keyboard::from_names(&KeymapNames::default()).expect("keymap");
37    let mut repeater = KeyRepeater::new(RepeatConfig::default()).expect("timer");
38
39    let started = Instant::now();
40    let mut events = Vec::new();
41    let mut repeats: Vec<KeyEvent> = Vec::new();
42    let mut leds = keyboard.leds();
43
44    loop {
45        {
46            let seat_fd = seat.as_fd();
47            let timer_fd = repeater.fd();
48            let mut fds = [
49                PollFd::new(&seat_fd, PollFlags::IN),
50                PollFd::new(&timer_fd, PollFlags::IN),
51            ];
52            let timeout = Duration::from_secs(30).try_into().expect("timeout");
53            if poll(&mut fds, Some(&timeout)).expect("poll") == 0 {
54                println!("nothing for thirty seconds");
55                return;
56            }
57        }
58
59        let now = u32::try_from(started.elapsed().as_millis()).unwrap_or(u32::MAX);
60
61        events.clear();
62        seat.dispatch(&mut events).expect("dispatch");
63        for event in &mut events {
64            match event {
65                InputEvent::Key(key) => {
66                    keyboard.process_key(key);
67                    repeater.on_key(key, keyboard.should_repeat(key.key));
68                    if report(key) {
69                        return;
70                    }
71                }
72                other => println!("{other:?}"),
73            }
74        }
75
76        repeats.clear();
77        repeater.dispatch(now, &mut repeats).expect("repeat");
78        for key in &mut repeats {
79            // Resolved, not replayed: a Shift pressed since the key went down
80            // changes what this types.
81            keyboard.resolve(key);
82            report(key);
83        }
84
85        let current = keyboard.leds();
86        if current != leds {
87            seat.set_leds(current);
88            leds = current;
89        }
90    }
91}
Source

pub fn set_leds(&mut self, desired: Leds)

Drive the lock state to desired.

By synthesizing a press and release of each lock key that is on the wrong side, which is the only way to move a latch xkb owns. Produces no events and does not disturb the held-key set.

For honoring a lock state from elsewhere – what the console had, what the session manager reports – and used internally by Keyboard::reload.

Source

pub fn held_keys(&self) -> &[u32]

The keys currently down, in evdev codes and press order.

Source

pub const fn keymap(&self) -> &Keymap

The compiled keymap, for a caller that needs to hand it on.

Trait Implementations§

Source§

impl Debug for Keyboard

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Nothing in xkb’s handles is printable, so this reports what is actually useful: the layouts compiled in and what is held down.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.