Commit graph

69 commits

Author SHA1 Message Date
Khoa Vo
42a0dad026 fix: Telex mode broken — is_vn_control_key consumed normal letters a/e/o/d/u
Only pure control keys (f,s,r,x,j,w) should be consumed silently.
Base letters used in double-letter marks (aa→â, ee→ê, etc.)
are normal typing keys that must be forwarded when no mark triggers.
Removed uppercase variants too — consolidated with to_ascii_lowercase().
2026-06-26 15:32:13 +07:00
Khoa Vo
d4102088b8 fix: X11 key lookup, bamboo engine port, uinput injection overhaul
- 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
2026-06-26 15:20:03 +07:00
Khoa Vo
ea5df93bce fix: aggressive drain to prevent feedback loop + clean up debug logging
- Add aggressive drain loop in wait_for_event() when SKIP_RECORD_EVENTS
  is true: poll 5ms + drain, repeat until quiet (up to 50ms). This closes
  the timing gap where injected events arrived after drain_pipe returned
  but before the flag was cleared in the next iteration.
- Remove verbose debug eprintln!/log_info from daemon (process_key,
  replay, inject, toggle, window change, etc.)
- Add vietc-xrecord.c (C helper with XRecordEnableContext blocking mode)
- Update build-appimage.sh to compile and bundle C helper
2026-06-26 11:45:57 +07:00
Khoa Vo
44d1b0a1d2 fix: XRecordInterceptData layout and data_len check
- Fixed struct to match C: id_base(u64), server_time(u64), client_seq(u64),
  category(i32), client_swapped(i32), data(ptr), data_len(u64)
- data_len is in 4-byte units, not bytes — keyboard events have data_len=1
- Added XRECORD_FROM_SERVER category check
- Removed re-grab logic from event loop
2026-06-26 10:16:58 +07:00
Khoa Vo
d1a5f36606 fix: remove XGrabKeyboard from XRecord path — it blocks event delivery
XGrabKeyboard on the same display as XRecord breaks event delivery.
XRecord captures events globally without any grab needed.
Also: use XPending() before select() to check Xlib internal buffer,
and add XFlush before XRecordProcessReplies after select().
2026-06-26 10:13:27 +07:00
Khoa Vo
7898768141 debug: add key event logging to trace XRecord flow 2026-06-26 10:08:13 +07:00
Khoa Vo
cca68004ab fix: use select() on X11 fd for reliable event detection
XPending returned 0 even with active keyboard grab. Using select() on
the X11 connection file descriptor with 100ms timeout to reliably detect
when the X server sends events. Also adds XSelectInput on root window
and XConnectionNumber for the fd.
2026-06-26 09:32:47 +07:00
Khoa Vo
666f1b400e fix: non-blocking XPending event loop + auto re-grab on grab loss
- Use XPending() to check for events before XNextEvent (non-blocking)
- Add is_grabbed() and has_pending_events() public methods
- Auto re-grab keyboard when grab is silently lost (tray, WM focus)
- Fixes AppImage daemon receiving zero keystroke events
2026-06-26 09:17:47 +07:00
Khoa Vo
3858aa955c feat: implement Backspace-Replay pattern for perfect engine sync
- Add Engine::replay_keystrokes() — creates fresh engine and replays
  all keystrokes to compute correct screen output from scratch
- Add Daemon::replay_and_inject() — tracks keystroke history and
  screen output, computes diff (backspaces + new text) on each keypress
- Add Daemon::replay_backspace() — pops from history, replays, diffs
- Handle flush chars (space, period, etc.) separately — commit word,
  type char, clear history
- Add FocusIn/FocusOut detection for engine reset on focus loss
- Add CPU pinning (P-cores 0-3) + nice(-10) priority boost
- Clean up 9 dead code warnings (unused fields, constants, types)
- Add replay_keystrokes tests for Telex, VNI, and backspace
- 255 tests pass (was 252)
2026-06-26 08:40:38 +07:00
Khoa Vo
bb0847a38f X11 capture: proper key tracking, direct clipboard, VNI default
- X11 keyboard capture via XGrabKeyboard (no input group needed)
- Direct X11 clipboard for Unicode injection (no xclip/xdotool dependency)
- Proper KeyPress/KeyRelease tracking (fix Ctrl+C, Alt+Tab, held keys)
- Default input_method=vni, start_enabled=false
- AppImage: bundled xclip, proper keyboard+VN SVG icon
- Deb: Recommends libxtst6, xclip
2026-06-26 07:56:52 +07:00
openhands
38f3bca022 Optimize typing performance and preserve casing on replaced syllables 2026-06-25 19:59:46 +07:00
vndangkhoa
5f8465783a Optimize typing performance and preserve casing on replaced syllables 2026-06-24 21:11:24 +07:00
vndangkhoa
a5c1ab99c3 Fix modifier key bypass (Ctrl, Alt, Meta) and raw key forwarding when no Vietnamese combination exists 2026-06-24 20:57:40 +07:00
vndangkhoa
f618c3a5b5 Fix typing race conditions with unified channel injection, add persistent logging, and align config schemas 2026-06-24 20:30:14 +07:00
vndangkhoa
42595d4bae Fix backspace in grab mode: inject KEY_BACKSPACE via uinput
When grab is enabled, the physical key is intercepted by evdev grab.
The engine's pop() updates the buffer but the KEY_BACKSPACE was never
injected — send_char('\x08') can't emit a keycode and fell through to
paste_string. Now backspace injects KEY_BACKSPACE press+release via
uinput directly.
2026-06-24 18:04:09 +07:00
vndangkhoa
0f1f08e79f Fix Unicode injection: ydotoold + xclip fallback + input logging
- Start ydotoold automatically so ydotool can handle Vietnamese chars
- Fix xclip clipboard to run as SUDO_USER when daemon is root
- Add detailed input logging for easier debugging
2026-06-24 17:41:04 +07:00
vndangkhoa
c3bc35ddce Fix garbled text: correct AppRun Wayland detection + atomic injection
- AppRun no longer sets WAYLAND_DISPLAY on X11 (checks for wayland socket)
- execute_commands now uses ydotool for both backspaces+text (same device)
- Merged execute_commands and execute_commands_with_grab into one function
- grab defaults to true in AppImage config
2026-06-24 17:33:13 +07:00
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
vndangkhoa
16a0d73a6e Viet+ v0.1.0 - Vietnamese Input Method for Linux
Features:
- Direct Input Engine (no pre-edit buffer, no underline)
- Telex + VNI input methods
- Auto-restore English words
- ESC undo (strip tones)
- Smart per-app memory
- Macro expansion (ko→không, dc→được, vs→với, lm→làm)
- Triple backend: uinput, X11 XTEST, Wayland IM
- Hot-reload config
- 148 tests passing

Packaging:
- .deb package
- AppImage support
- AUR PKGBUILD
- Flatpak manifest
- Systemd user service
2026-06-24 10:13:10 +07:00