96 lines
2.1 KiB
Rust
96 lines
2.1 KiB
Rust
// This code is a port of the libxkbcommon "interactive-evdev.c" example
|
|
// https://github.com/xkbcommon/libxkbcommon/blob/master/tools/interactive-evdev.c
|
|
|
|
use std::{ffi::CStr, os::raw::c_char};
|
|
|
|
use scopeguard::ScopeGuard;
|
|
|
|
use anyhow::Result;
|
|
use thiserror::Error;
|
|
|
|
use super::{
|
|
ffi::{
|
|
xkb_state, xkb_state_key_get_one_sym, xkb_state_key_get_utf8, xkb_state_new, xkb_state_unref,
|
|
xkb_state_update_key,
|
|
},
|
|
keymap::Keymap,
|
|
};
|
|
|
|
pub struct State {
|
|
state: *mut xkb_state,
|
|
}
|
|
|
|
impl State {
|
|
pub fn new(keymap: &Keymap) -> Result<State> {
|
|
let raw_state = unsafe { xkb_state_new(keymap.get_handle()) };
|
|
let state = scopeguard::guard(raw_state, |raw_state| unsafe {
|
|
xkb_state_unref(raw_state);
|
|
});
|
|
|
|
if raw_state.is_null() {
|
|
return Err(StateError::FailedCreation().into());
|
|
}
|
|
|
|
Ok(Self {
|
|
state: ScopeGuard::into_inner(state),
|
|
})
|
|
}
|
|
|
|
pub fn update_key(&self, code: u32, pressed: bool) {
|
|
let direction = if pressed {
|
|
super::ffi::xkb_key_direction::DOWN
|
|
} else {
|
|
super::ffi::xkb_key_direction::UP
|
|
};
|
|
unsafe {
|
|
xkb_state_update_key(self.state, code, direction);
|
|
}
|
|
}
|
|
|
|
pub fn get_string(&self, code: u32) -> Option<String> {
|
|
let mut buffer: [c_char; 16] = [0; 16];
|
|
let len = unsafe {
|
|
xkb_state_key_get_utf8(
|
|
self.state,
|
|
code,
|
|
buffer.as_mut_ptr(),
|
|
std::mem::size_of_val(&buffer),
|
|
)
|
|
};
|
|
if len > 0 {
|
|
let content_raw = unsafe { CStr::from_ptr(buffer.as_ptr()) };
|
|
let string = content_raw.to_string_lossy().to_string();
|
|
if string.is_empty() {
|
|
None
|
|
} else {
|
|
Some(string)
|
|
}
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub fn get_sym(&self, code: u32) -> Option<u32> {
|
|
let sym = unsafe { xkb_state_key_get_one_sym(self.state, code) };
|
|
if sym == 0 {
|
|
None
|
|
} else {
|
|
Some(sym)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Drop for State {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
xkb_state_unref(self.state);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum StateError {
|
|
#[error("could not create xkb state")]
|
|
FailedCreation(),
|
|
}
|