vietc/protocol/src/inject.rs
vndangkhoa 95f661aaa0 Viet+ v0.1.1
- 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
2026-06-24 17:29:12 +07:00

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"),
}
}
}