- Fix Xutf8LookupString signature (missing XIC param caused all keys to map to \0) - Port bamboo-core Vietnamese engine to Rust (bamboo.rs, input_method.rs) - Flexible backtracking for mark/tone keys (scan up to 5 chars back) - Correct tone placement for io, uâ, yê clusters - Evdev capture preferred over X11 XRecord (more reliable) - Uinput injection with correct Linux keycodes - Vietnamese Unicode via clipboard paste + trailing ASCII via uinput - Persistent X11 connection for Ctrl+V (no per-call dlopen overhead) - Consume stale VNI/Telex control keys when no match found - Fix execute_commands backspace count for evdev grabbing path - Add vietc-uinputd privileged injection daemon - AppImage: bundle uinputd, preserve LD_LIBRARY_PATH, fix xrecord build flags - Remove old generated test files, add 63 focused engine tests
75 lines
2.1 KiB
Rust
75 lines
2.1 KiB
Rust
use std::io::{BufRead, BufReader, Write};
|
|
use std::os::unix::net::UnixStream;
|
|
use std::path::PathBuf;
|
|
|
|
use super::inject::{InjectResult, KeyInjector};
|
|
|
|
fn socket_path() -> PathBuf {
|
|
let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".into());
|
|
PathBuf::from(home).join(".vietc").join("uinput.sock")
|
|
}
|
|
|
|
pub struct UinputClient;
|
|
|
|
impl UinputClient {
|
|
fn send_command(cmd: &str) -> InjectResult {
|
|
match UnixStream::connect(socket_path()) {
|
|
Ok(mut stream) => {
|
|
if writeln!(stream, "{}", cmd).is_err() {
|
|
return InjectResult::Failed;
|
|
}
|
|
let mut reader = BufReader::new(&stream);
|
|
let mut response = String::new();
|
|
if reader.read_line(&mut response).is_err() {
|
|
return InjectResult::Failed;
|
|
}
|
|
if response.trim() == "OK" {
|
|
InjectResult::Success
|
|
} else {
|
|
InjectResult::Failed
|
|
}
|
|
}
|
|
Err(_) => InjectResult::Failed,
|
|
}
|
|
}
|
|
|
|
pub fn is_available() -> bool {
|
|
UnixStream::connect(socket_path()).is_ok()
|
|
}
|
|
}
|
|
|
|
impl KeyInjector for UinputClient {
|
|
fn send_key_event(&self, _keycode: u16, _value: i32) -> InjectResult {
|
|
InjectResult::Success
|
|
}
|
|
|
|
fn send_backspace(&self) -> InjectResult {
|
|
InjectResult::Success
|
|
}
|
|
|
|
fn send_char(&self, _ch: char) -> InjectResult {
|
|
InjectResult::Success
|
|
}
|
|
|
|
fn send_string(&self, s: &str) -> InjectResult {
|
|
Self::send_command(&format!("TYPE:{}", s))
|
|
}
|
|
|
|
fn inject_replacement(&self, backspaces: usize, text: &str) -> InjectResult {
|
|
if backspaces > 0 {
|
|
let _ = Self::send_command(&format!("BACKSPACE:{}", backspaces));
|
|
}
|
|
if !text.is_empty() {
|
|
let _ = Self::send_command(&format!("TYPE:{}", text));
|
|
}
|
|
InjectResult::Success
|
|
}
|
|
|
|
fn flush(&self) -> InjectResult {
|
|
InjectResult::Success
|
|
}
|
|
|
|
fn update_pasted_text(&self, _text: &str) -> InjectResult {
|
|
InjectResult::Success
|
|
}
|
|
}
|