236 lines
7.6 KiB
Rust
236 lines
7.6 KiB
Rust
// SPDX-License-Identifier: GPL-3.0-only
|
|
/*
|
|
* Copyright (c) 2024, Richard Acayan. All rights reserved.
|
|
*/
|
|
|
|
use std::convert::TryInto;
|
|
use std::fs::File;
|
|
use rgb::alt::BGR;
|
|
use rgb::alt::BGRA;
|
|
use rgb::RGB;
|
|
use yaml_rust2::yaml::Hash;
|
|
use yaml_rust2::yaml::LoadError;
|
|
use yaml_rust2::yaml::YamlDecoder;
|
|
use yaml_rust2::yaml::Yaml;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct KeyboardColors {
|
|
pub background: BGRA<u8>,
|
|
pub keycap: BGRA<u8>,
|
|
pub keycap_pressed: BGRA<u8>,
|
|
pub label: BGR<u8>,
|
|
pub label_locked: BGR<u8>,
|
|
pub label_pressed: BGR<u8>,
|
|
pub sublabel: BGR<u8>,
|
|
}
|
|
|
|
impl Default for KeyboardColors {
|
|
fn default() -> Self
|
|
{
|
|
Self {
|
|
background: RGB::new(0, 0, 0).into(),
|
|
keycap: RGB::new(0, 0, 0).into(),
|
|
keycap_pressed: RGB::new(51,51,51).into(),
|
|
label: RGB::new(255, 255, 255).into(),
|
|
label_locked: RGB::new(25, 255, 0).into(),
|
|
label_pressed: RGB::new(255, 153, 0).into(),
|
|
sublabel: RGB::new(178, 178, 178).into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn parse_color(yaml: &Yaml) -> Option<RGB<u8>>
|
|
{
|
|
let mut color_bytes = yaml
|
|
.as_vec()?
|
|
.iter()
|
|
.map_while(|b| b.as_i64())
|
|
.map_while(|b| b.try_into().ok());
|
|
|
|
Some(RGB::new(
|
|
color_bytes.next()?,
|
|
color_bytes.next()?,
|
|
color_bytes.next()?
|
|
))
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Configuration {
|
|
longpress: u64,
|
|
repeat: u64,
|
|
layout: String,
|
|
extra_keys: Vec<String>,
|
|
wayland_height: i32,
|
|
wayland_im_enable: bool,
|
|
|
|
colors: KeyboardColors,
|
|
}
|
|
|
|
impl Configuration {
|
|
fn load_wayland(&mut self, yaml: &Hash)
|
|
{
|
|
let height = yaml.get(&Yaml::String(String::from("height")));
|
|
if let Some(height) = height {
|
|
let height = match height.as_i64() {
|
|
Some(h) => h.try_into().ok(),
|
|
None => None,
|
|
};
|
|
let height = height.expect("Wayland height should be a 32-bit signed integer");
|
|
self.wayland_height = height;
|
|
}
|
|
|
|
let im_enable = yaml.get(&Yaml::String(String::from("input-method")));
|
|
if let Some(im_enable) = im_enable {
|
|
let im_enable = im_enable.as_bool();
|
|
let im_enable = im_enable.expect("Wayland height should be a 32-bit signed integer");
|
|
self.wayland_im_enable = im_enable;
|
|
}
|
|
}
|
|
|
|
fn load_colors(&mut self, yaml: &Hash)
|
|
{
|
|
if let Some(keycap) = yaml.get(&Yaml::String(String::from("keycap"))) {
|
|
self.colors.keycap = parse_color(keycap)
|
|
.expect("Keycap color needs to be a list of 3 8-bit unsigned integers")
|
|
.into();
|
|
}
|
|
if let Some(keycap_pressed) = yaml.get(&Yaml::String(String::from("keycap_pressed"))) {
|
|
self.colors.keycap_pressed = parse_color(keycap_pressed)
|
|
.expect("Keycap pressed color needs to be a list of 3 8-bit unsigned integers")
|
|
.into();
|
|
}
|
|
if let Some(label) = yaml.get(&Yaml::String(String::from("label"))) {
|
|
self.colors.label = parse_color(label)
|
|
.expect("Label color needs to be a list of 3 8-bit unsigned integers")
|
|
.into();
|
|
}
|
|
if let Some(label_pressed) = yaml.get(&Yaml::String(String::from("label_pressed"))) {
|
|
self.colors.label_pressed = parse_color(label_pressed)
|
|
.expect("Label pressed color needs to be a list of 3 8-bit unsigned integers")
|
|
.into();
|
|
}
|
|
if let Some(label_locked) = yaml.get(&Yaml::String(String::from("label_locked"))) {
|
|
self.colors.label_locked = parse_color(label_locked)
|
|
.expect("Label locked color needs to be a list of 3 8-bit unsigned integers")
|
|
.into();
|
|
}
|
|
if let Some(sublabel) = yaml.get(&Yaml::String(String::from("sublabel"))) {
|
|
self.colors.sublabel = parse_color(sublabel)
|
|
.expect("Sublabel color needs to be a list of 3 8-bit unsigned integers")
|
|
.into();
|
|
}
|
|
if let Some(background) = yaml.get(&Yaml::String(String::from("background"))) {
|
|
self.colors.background = parse_color(background)
|
|
.expect("Background color needs to be a list of 3 8-bit unsigned integers")
|
|
.into();
|
|
}
|
|
}
|
|
|
|
pub fn load() -> Result<Self, LoadError>
|
|
{
|
|
let mut cfg = Configuration {
|
|
longpress: 600,
|
|
repeat: 25,
|
|
layout: String::from("latn_qwerty_us.xml"),
|
|
extra_keys: vec![ String::from("alt"), String::from("meta") ],
|
|
wayland_height: 185,
|
|
wayland_im_enable: true,
|
|
|
|
colors: KeyboardColors::default(),
|
|
};
|
|
|
|
if let Ok(file) = File::open("/etc/unfettered-keyboard.yaml") {
|
|
let yaml = YamlDecoder::read(file).decode()?;
|
|
let yaml = yaml[0].as_hash().expect("Top-level configuration should be a YAML mapping");
|
|
|
|
let longpress = yaml.get(&Yaml::String(String::from("longpress_ms")));
|
|
if let Some(longpress) = longpress {
|
|
let longpress = match longpress.as_i64() {
|
|
Some(l) => l.try_into().ok(),
|
|
None => None,
|
|
};
|
|
let longpress = longpress.expect("Longpress time should be a 64-bit unsigned integer");
|
|
cfg.longpress = longpress;
|
|
}
|
|
|
|
let repeat = yaml.get(&Yaml::String(String::from("repeat_ms")));
|
|
if let Some(repeat) = repeat {
|
|
let repeat = match repeat.as_i64() {
|
|
Some(l) => l.try_into().ok(),
|
|
None => None,
|
|
};
|
|
let repeat = repeat.expect("Repeat interval should be a 64-bit unsigned integer");
|
|
cfg.repeat = repeat;
|
|
}
|
|
|
|
let layout = yaml.get(&Yaml::String(String::from("layout")));
|
|
if let Some(layout) = layout {
|
|
let layout = layout.as_str().expect("Layout should be a YAML string");
|
|
cfg.layout = layout.to_string();
|
|
}
|
|
|
|
let keys = yaml.get(&Yaml::String(String::from("extra_keys")));
|
|
if let Some(keys) = keys {
|
|
let keys = keys.as_vec().expect("Extra keys should be a list");
|
|
cfg.extra_keys = keys.iter().map(|y| String::from(y.as_str().unwrap())).collect();
|
|
cfg.extra_keys.sort_unstable();
|
|
}
|
|
|
|
let wl = yaml.get(&Yaml::String(String::from("wayland")));
|
|
if let Some(wl) = wl {
|
|
let wl = wl.as_hash().expect("Wayland configuration should be a YAML mapping");
|
|
cfg.load_wayland(wl);
|
|
}
|
|
|
|
let colors = yaml.get(&Yaml::String(String::from("colors")));
|
|
if let Some(colors) = colors {
|
|
let colors = colors.as_hash().expect("Color configuration should be a YAML mapping");
|
|
cfg.load_colors(colors);
|
|
}
|
|
}
|
|
|
|
Ok(cfg)
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn longpress_ms(&self) -> u64
|
|
{
|
|
self.longpress
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn repeat_ms(&self) -> u64
|
|
{
|
|
self.repeat
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn layout(&self) -> &str
|
|
{
|
|
&self.layout
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn extra_keys(&self) -> &Vec<String>
|
|
{
|
|
&self.extra_keys
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn wayland_height(&self) -> i32
|
|
{
|
|
self.wayland_height
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn wayland_im_enable(&self) -> bool
|
|
{
|
|
self.wayland_im_enable
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn colors(&self) -> &KeyboardColors
|
|
{
|
|
&self.colors
|
|
}
|
|
}
|