- Flexible diacritic placement: modifiers/tone marks at end of syllable (Telex: tranaf -> tran, VNI: tran62 -> tran) - uinput injector as primary backend (avoids X11/Unicode ordering bugs) - ydotool for atomic backspace+text injection (same uinput device) - Fix run_as_user to use explicit 'env VAR=val' (sudo compat) - Remove deb/flatpak/aur packaging (AppImage only) - Fix Telex key mappings (aa=aa, aw=a, ow=o) - Fix VNI key mappings (a6=aa, a8=a, e6=e, o6=o, o7=o, u7=u) - Fix X11Injector ydotool fallback for Unicode chars - 162+ engine tests passing
77 lines
1.9 KiB
Rust
77 lines
1.9 KiB
Rust
use std::fmt;
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum KeyAction {
|
|
Press,
|
|
Release,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct KeyEvent {
|
|
pub code: u32,
|
|
pub value: char,
|
|
pub action: KeyAction,
|
|
}
|
|
|
|
impl KeyEvent {
|
|
pub fn press(code: u32, value: char) -> Self {
|
|
Self { code, value, action: KeyAction::Press }
|
|
}
|
|
|
|
pub fn release(code: u32, value: char) -> Self {
|
|
Self { code, value, action: KeyAction::Release }
|
|
}
|
|
|
|
pub fn is_press(&self) -> bool {
|
|
self.action == KeyAction::Press
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum InjectResult {
|
|
Success,
|
|
Failed,
|
|
NotSupported,
|
|
}
|
|
|
|
impl InjectResult {
|
|
pub fn is_ok(&self) -> bool {
|
|
*self == InjectResult::Success
|
|
}
|
|
}
|
|
|
|
pub trait KeyInjector {
|
|
fn send_backspace(&self) -> InjectResult;
|
|
fn send_char(&self, ch: char) -> InjectResult;
|
|
fn send_string(&self, s: &str) -> InjectResult;
|
|
fn send_key_event(&self, _keycode: u16, _value: i32) -> InjectResult {
|
|
InjectResult::NotSupported
|
|
}
|
|
fn flush(&self) -> InjectResult;
|
|
|
|
fn send_backspaces(&self, count: usize) -> InjectResult {
|
|
for _ in 0..count {
|
|
if self.send_backspace() != InjectResult::Success {
|
|
return InjectResult::Failed;
|
|
}
|
|
}
|
|
InjectResult::Success
|
|
}
|
|
|
|
fn inject_replacement(&self, backspaces: usize, text: &str) -> InjectResult {
|
|
if self.send_backspaces(backspaces) != InjectResult::Success {
|
|
return InjectResult::Failed;
|
|
}
|
|
self.send_string(text)
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for InjectResult {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
InjectResult::Success => write!(f, "Success"),
|
|
InjectResult::Failed => write!(f, "Failed"),
|
|
InjectResult::NotSupported => write!(f, "NotSupported"),
|
|
}
|
|
}
|
|
}
|