Create kdb handler from RMLVO rules
This commit is contained in:
parent
a7117369a2
commit
4adcadd937
|
@ -7,7 +7,7 @@
|
||||||
//! The handle you obtained can be cloned to access this keyboard state from different places. It is
|
//! The handle you obtained can be cloned to access this keyboard state from different places. It is
|
||||||
//! expected that such a context is created for each keyboard the compositor has access to.
|
//! expected that such a context is created for each keyboard the compositor has access to.
|
||||||
//!
|
//!
|
||||||
//! This handle gives you 3 main way to interact with the keymap handling:
|
//! This handle gives you 3 main ways to interact with the keymap handling:
|
||||||
//!
|
//!
|
||||||
//! - send the keymap information to a client using the `KbdHandle::send_keymap` method.
|
//! - send the keymap information to a client using the `KbdHandle::send_keymap` method.
|
||||||
//! - set the current focus for this keyboard: designing the client that will receive the key inputs
|
//! - set the current focus for this keyboard: designing the client that will receive the key inputs
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
|
|
||||||
use backend::input::KeyState;
|
use backend::input::KeyState;
|
||||||
use std::io::Write;
|
use std::io::{Error as IoError, Write};
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
@ -81,23 +81,33 @@ struct KbdInternal {
|
||||||
focus: Option<(wl_surface::WlSurface, wl_keyboard::WlKeyboard)>,
|
focus: Option<(wl_surface::WlSurface, wl_keyboard::WlKeyboard)>,
|
||||||
pressed_keys: Vec<u32>,
|
pressed_keys: Vec<u32>,
|
||||||
mods_state: ModifiersState,
|
mods_state: ModifiersState,
|
||||||
_context: xkb::Context,
|
|
||||||
keymap: xkb::Keymap,
|
keymap: xkb::Keymap,
|
||||||
state: xkb::State,
|
state: xkb::State,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KbdInternal {
|
impl KbdInternal {
|
||||||
fn new() -> Result<KbdInternal, ()> {
|
fn new(rules: &str, model: &str, layout: &str, variant: &str, options: Option<String>)
|
||||||
|
-> Result<KbdInternal, ()> {
|
||||||
|
// we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe
|
||||||
|
// so confining it inside the KbdInternal allows us to use Rusts mutability rules to make
|
||||||
|
// sure nothing goes wrong.
|
||||||
|
//
|
||||||
|
// FIXME: This is an issue with the xkbcommon-rs crate that does not reflect this
|
||||||
|
// non-threadsafety properly.
|
||||||
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||||
// TODO: api to choose the keymap to load
|
let keymap = xkb::Keymap::new_from_names(&context,
|
||||||
let keymap = xkb::Keymap::new_from_names(&context, &"", &"", &"fr", &"oss", None, 0)
|
&rules,
|
||||||
.ok_or(())?;
|
&model,
|
||||||
|
&layout,
|
||||||
|
&variant,
|
||||||
|
options,
|
||||||
|
xkb::KEYMAP_COMPILE_NO_FLAGS)
|
||||||
|
.ok_or(())?;
|
||||||
let state = xkb::State::new(&keymap);
|
let state = xkb::State::new(&keymap);
|
||||||
Ok(KbdInternal {
|
Ok(KbdInternal {
|
||||||
focus: None,
|
focus: None,
|
||||||
pressed_keys: Vec::new(),
|
pressed_keys: Vec::new(),
|
||||||
mods_state: ModifiersState::new(),
|
mods_state: ModifiersState::new(),
|
||||||
_context: context,
|
|
||||||
keymap: keymap,
|
keymap: keymap,
|
||||||
state: state,
|
state: state,
|
||||||
})
|
})
|
||||||
|
@ -145,15 +155,28 @@ impl KbdInternal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_keyboard_handler() -> Result<KbdHandle, ()> {
|
/// Errors that can be encountered when creating a keyboard handler
|
||||||
let internal = KbdInternal::new()?;
|
pub enum Error {
|
||||||
|
/// libxkbcommon could not load the specified keymap
|
||||||
|
BadKeymap,
|
||||||
|
/// Smithay could not create a tempfile to share the keymap with clients
|
||||||
|
IoError(IoError),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a keyboard handler from a set of RMLVO rules
|
||||||
|
pub fn create_keyboard_handler(rules: &str, model: &str, layout: &str, variant: &str,
|
||||||
|
options: Option<String>)
|
||||||
|
-> Result<KbdHandle, Error> {
|
||||||
|
let internal = KbdInternal::new(rules, model, layout, variant, options)
|
||||||
|
.map_err(|_| Error::BadKeymap)?;
|
||||||
|
|
||||||
// prepare a tempfile with the keymap, to send it to clients
|
// prepare a tempfile with the keymap, to send it to clients
|
||||||
// TODO: better error handling
|
let mut keymap_file = tempfile().map_err(Error::IoError)?;
|
||||||
let mut keymap_file = tempfile().unwrap();
|
|
||||||
let keymap_data = internal.keymap.get_as_string(xkb::KEYMAP_FORMAT_TEXT_V1);
|
let keymap_data = internal.keymap.get_as_string(xkb::KEYMAP_FORMAT_TEXT_V1);
|
||||||
keymap_file.write_all(keymap_data.as_bytes()).unwrap();
|
keymap_file
|
||||||
keymap_file.flush().unwrap();
|
.write_all(keymap_data.as_bytes())
|
||||||
|
.map_err(Error::IoError)?;
|
||||||
|
keymap_file.flush().map_err(Error::IoError)?;
|
||||||
|
|
||||||
Ok(KbdHandle {
|
Ok(KbdHandle {
|
||||||
internal: Arc::new((Mutex::new(internal), (keymap_file, keymap_data.as_bytes().len() as u32))),
|
internal: Arc::new((Mutex::new(internal), (keymap_file, keymap_data.as_bytes().len() as u32))),
|
||||||
|
|
Loading…
Reference in New Issue