Compose file loading

This commit is contained in:
Jakub Hlusička 2026-01-07 03:33:22 +01:00
parent 56f8b52cf9
commit 1f21d29bd2
6 changed files with 5229 additions and 1133 deletions

11
firmware2/Cargo.lock generated
View file

@ -37,6 +37,7 @@ dependencies = [
"mutually_exclusive_features", "mutually_exclusive_features",
"panic-rtt-target", "panic-rtt-target",
"paste", "paste",
"printf-compat",
"rand_core 0.6.4", "rand_core 0.6.4",
"rmk", "rmk",
"rtt-target", "rtt-target",
@ -5581,6 +5582,16 @@ dependencies = [
"elliptic-curve", "elliptic-curve",
] ]
[[package]]
name = "printf-compat"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ccd7bb33c3c13016f1315e4e4c6ad1d0021ce575b1e254868f4330eab99e1b6"
dependencies = [
"bitflags 2.10.0",
"itertools 0.14.0",
]
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "3.4.0" version = "3.4.0"

View file

@ -74,12 +74,13 @@ cfg-if = "1.0.4"
xkbcommon = { path = "../../../rust/xkbcommon-rs-ffi", default-features = false, features = ["tinyrlibc"] } xkbcommon = { path = "../../../rust/xkbcommon-rs-ffi", default-features = false, features = ["tinyrlibc"] }
rtt-target = { version = "0.6.2", features = ["log"], optional = true } rtt-target = { version = "0.6.2", features = ["log"], optional = true }
panic-rtt-target = { version = "0.2.0", optional = true } panic-rtt-target = { version = "0.2.0", optional = true }
enumset = "1.1.10"
printf-compat = { version = "0.2.1", default-features = false }
# Crates for serial UART CLI # Crates for serial UART CLI
embedded-cli = { version = "0.2.1", default-features = false, features = ["help", "macros"] } embedded-cli = { version = "0.2.1", default-features = false, features = ["help", "macros"] }
embedded-io = "0.6.1" embedded-io = "0.6.1"
mutually_exclusive_features = "0.1.0" mutually_exclusive_features = "0.1.0"
enumset = "1.1.10"
[build-dependencies] [build-dependencies]
xz2 = "0.1.7" xz2 = "0.1.7"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -3,11 +3,19 @@
#![allow(unused_variables)] #![allow(unused_variables)]
use core::ffi::{VaList, c_char, c_int, c_long, c_size_t, c_void}; use core::{
ffi::{CStr, VaList, c_char, c_int, c_long, c_size_t, c_void},
ptr::null_mut,
};
use log::info; use alloc::string::String;
use log::{info, warn};
use printf_compat::output::fmt_write;
use crate::ffi::inout::file::{FILE, STDERR, STDOUT}; use crate::ffi::{
inout::file::{FILE, STDERR, STDOUT},
string::__xkbc_memcpy,
};
pub mod dir; pub mod dir;
pub mod file; pub mod file;
@ -16,7 +24,11 @@ pub mod file;
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE { pub unsafe extern "C" fn __xkbc_fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE {
todo!() warn!(
"The xkbcommon library is attempting to open a file at path: {:?}",
unsafe { CStr::from_ptr(filename) }
);
null_mut()
} }
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
@ -62,7 +74,12 @@ pub unsafe extern "C" fn __xkbc_vfprintf(
ap: VaList, ap: VaList,
) -> c_int { ) -> c_int {
if stream == STDOUT || stream == STDERR { if stream == STDOUT || stream == STDERR {
let string = ::alloc::format!("vfprintf({:?}, {:?}, {:?})", stream, format, ap); let string = ::alloc::format!(
"vfprintf({:?}, {:?}, {:?})",
stream,
unsafe { CStr::from_ptr(format) },
ap
);
info!("{}", string); info!("{}", string);
string.len() as c_int string.len() as c_int
} else { } else {
@ -79,22 +96,50 @@ pub unsafe extern "C" fn __xkbc_vasprintf(
todo!() todo!()
} }
// FIXME/TODO: This shouldn't be necessary. We need to rename the symbol in libxkbcommon.a(src_compose_state.c.o).
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_vsnprintf( pub unsafe extern "C" fn snprintf(
string: *mut c_char, string: *mut c_char,
size: c_size_t, size: c_size_t,
format: *const c_char, format: *const c_char,
ap: VaList, mut args: ...
) -> c_int { ) -> c_int {
todo!() unsafe { __xkbc_vsnprintf(string, size, format, args.as_va_list()) }
} }
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_snprintf( pub unsafe extern "C" fn __xkbc_snprintf(
s: *mut c_char, string: *mut c_char,
n: c_size_t, size: c_size_t,
format: *const c_char, format: *const c_char,
... mut args: ...
) -> c_int { ) -> c_int {
todo!() unsafe { __xkbc_vsnprintf(string, size, format, args.as_va_list()) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_vsnprintf(
string: *mut c_char,
// Length in bytes **including the terminating null byte**.
size: c_size_t,
format: *const c_char,
ap: VaList,
) -> c_int {
if size == 0 {
return 0;
}
let mut rust_buffer = String::new();
unsafe {
printf_compat::format(format, ap, fmt_write(&mut rust_buffer));
let string_length = core::cmp::min(rust_buffer.len(), size - 1);
// __xkbc_strncpy would be preferrable, if it was available
__xkbc_memcpy(
string as *mut _,
rust_buffer.as_ptr() as *mut _,
string_length,
);
*string.add(string_length) = 0; // Add terminating null byte.
string_length as c_int
}
} }

View file

@ -61,7 +61,7 @@ use slint::ComponentHandle;
use slint::platform::software_renderer::Rgb565Pixel; use slint::platform::software_renderer::Rgb565Pixel;
use static_cell::StaticCell; use static_cell::StaticCell;
use ui::AppWindow; use ui::AppWindow;
use xkbcommon::xkb::{self, KeyDirection}; use xkbcommon::xkb::{self, KeyDirection, ModIndex};
use {esp_alloc as _, esp_backtrace as _}; use {esp_alloc as _, esp_backtrace as _};
use crate::matrix::IoeMatrix; use crate::matrix::IoeMatrix;
@ -418,7 +418,7 @@ async fn main(_spawner: Spawner) {
Box::from_raw_in(slice as *mut str, &PSRAM_ALLOCATOR) Box::from_raw_in(slice as *mut str, &PSRAM_ALLOCATOR)
}; };
let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
info!("Parsing XKB keymap..."); info!("Loading XKB keymap...");
let instant_start = Instant::now(); let instant_start = Instant::now();
let keymap = xkb::Keymap::new_from_string( let keymap = xkb::Keymap::new_from_string(
&context, &context,
@ -429,18 +429,40 @@ async fn main(_spawner: Spawner) {
.unwrap(); .unwrap();
let duration = Instant::now().duration_since(instant_start); let duration = Instant::now().duration_since(instant_start);
info!( info!(
"XKB keymap parsed successfully! Took {seconds}.{millis:03} seconds.", "XKB keymap loaded successfully! Took {seconds}.{millis:03} seconds.",
seconds = duration.as_secs(),
millis = duration.as_millis() % 1_000
);
info!("Loading XKB compose map...");
let instant_start = Instant::now();
const COMPOSE_MAP_STRING: &str = include_str!("../compose/cs_CZ Compose.txt");
const COMPOSE_MAP_LOCALE: &str = "cs_CZ.UTF-8";
let compose_table = xkb::compose::Table::new_from_buffer(
&context,
COMPOSE_MAP_STRING,
COMPOSE_MAP_LOCALE,
xkb::compose::FORMAT_TEXT_V1,
xkb::compose::COMPILE_NO_FLAGS,
)
.unwrap();
let duration = Instant::now().duration_since(instant_start);
info!(
"XKB compose map loaded successfully! Took {seconds}.{millis:03} seconds.",
seconds = duration.as_secs(), seconds = duration.as_secs(),
millis = duration.as_millis() % 1_000 millis = duration.as_millis() % 1_000
); );
let mut state = xkb::State::new(&keymap); let mut state = xkb::State::new(&keymap);
let mut previous_state = KeyboardReport::default(); let mut previous_state = KeyboardReport::default();
let mut compose_state =
xkb::compose::State::new(&compose_table, xkb::compose::STATE_NO_FLAGS);
async move { async move {
loop { loop {
let report = KEYBOARD_REPORT_PROXY.receive().await; let report = KEYBOARD_REPORT_PROXY.receive().await;
if let Report::KeyboardReport(report) = &report { if let Report::KeyboardReport(report) = &report {
warn!("MODIFIERS = {:02x}", report.modifier);
const RMK_ALT: u8 = 0xE2;
// TODO: Process modifiers // TODO: Process modifiers
for (keycode_old, &keycode_new) in for (keycode_old, &keycode_new) in
@ -491,15 +513,21 @@ async fn main(_spawner: Spawner) {
if *keycode_old == 0 || ((keycode_new != 0) && *keycode_old != keycode_new) if *keycode_old == 0 || ((keycode_new != 0) && *keycode_old != keycode_new)
{ {
let keycode_new_xkb = into_xkb_keycode(keycode_new); let keycode_new_xkb = into_xkb_keycode(keycode_new);
let string = state.key_get_utf8(keycode_new_xkb); let syms = state.key_get_syms(keycode_new_xkb);
for sym in syms {
compose_state.feed(*sym);
}
let string = compose_state.utf8();
warn!("Pressed: 0x{:02x} ({})", keycode_new, keycode_new); warn!("Pressed: 0x{:02x} ({})", keycode_new, keycode_new);
warn!("Print: {string}"); warn!("Syms: {syms:?}");
warn!("String: {string:?}");
state.update_key(keycode_new_xkb, KeyDirection::Down); state.update_key(keycode_new_xkb, KeyDirection::Down);
} }
// state.update_key(keycode, direction);
*keycode_old = keycode_new; *keycode_old = keycode_new;
} }
} }