cognitive_inputs/keymap.rs
1// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
2// the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/
3
4//! This module contains functionality related to key maps.
5
6// -------------------------------------------------------------------------------------------------
7
8use std;
9use std::os::unix::io::AsRawFd;
10use std::io::Write;
11use xkbcommon::xkb;
12
13use qualia::{Illusion, KeyboardConfig, KeymapSettings, env};
14
15// -------------------------------------------------------------------------------------------------
16
17const DEFAULT_FORMAT: u32 = xkb::KEYMAP_FORMAT_TEXT_V1;
18
19// -------------------------------------------------------------------------------------------------
20
21/// Wrapper for `xkb` context and keymap.
22pub struct XkbKeymap {
23 pub context: xkb::Context,
24 pub keymap: xkb::Keymap,
25}
26
27// -------------------------------------------------------------------------------------------------
28
29impl XkbKeymap {
30 /// Constructs new `XkbKeymap`.
31 pub fn new(config: &KeyboardConfig) -> Option<Self> {
32 let rules = "evdev".to_owned();
33 let model = "evdev".to_owned();
34 let layout = &config.layout;
35 let variant = &config.variant;
36
37 let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
38 let k = xkb::Keymap::new_from_names(&context, &rules, &model, layout, variant, None, 0x0);
39 if let Some(keymap) = k {
40 Some(XkbKeymap {
41 context: context,
42 keymap: keymap,
43 })
44 } else {
45 None
46 }
47 }
48}
49
50// -------------------------------------------------------------------------------------------------
51
52/// This structure handles creation of file used for communicating clients current keymap using
53/// xkbcommon.
54pub struct Keymap {
55 settings: KeymapSettings,
56
57 /// Keymap file. It is not referenced here but must be kept open because we will pass file
58 /// descriptor to clients.
59 _file: std::fs::File,
60}
61
62// -------------------------------------------------------------------------------------------------
63
64impl Keymap {
65 /// `Keymap` constructor.
66 pub fn new(env: &env::Env, config: &KeyboardConfig) -> Result<Self, Illusion> {
67 let xkb_keymap = if let Some(xkb_keymap) = XkbKeymap::new(config) {
68 xkb_keymap
69 } else {
70 return Err(Illusion::General(format!("Failed to create key map")));
71 };
72
73 // Save keymap to file
74 let file_name = "keymap".to_owned();
75 let keymap_str = xkb_keymap.keymap.get_as_string(DEFAULT_FORMAT);
76 let mut file = env.open_file(file_name, env::Directory::Runtime)?;
77 file.write_all(keymap_str.as_bytes())?;
78 file.write_all("\0".as_bytes())?;
79
80 Ok(Keymap {
81 settings: KeymapSettings {
82 format: DEFAULT_FORMAT,
83 size: keymap_str.len() + 1,
84 fd: file.as_raw_fd(),
85 },
86 _file: file,
87 })
88 }
89
90 /// Return key map settings.
91 pub fn get_settings(&self) -> KeymapSettings {
92 self.settings.clone()
93 }
94}
95
96// -------------------------------------------------------------------------------------------------