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// -------------------------------------------------------------------------------------------------