A modern Vietnamese Input Method Engine (IME) for Linux with direct Unicode input—no pre-edit buffer, no underlines.
Find a file
Khoa Vo 5f0f059139 fix: non-grabbed evdev on X11 — switch to XTest injection for instant correction
On X11, uinput injection has high latency (kernel → libinput → X server)
compared to XTest' which writes events directly into the X11 event queue.
Physical key events reach the app before the uinput backspace correction,
causing the VNI control key digit to flash on screen.

Fix: when non-grabbed mode is entered on X11 (grab failed or ungrab),
replace the uinput injector with X11Injector (XTest). XTest events
are processed synchronously by X server and take effect before
subsequent physical events.
2026-07-04 18:20:53 +07:00
.github/workflows production: download prebuilt binaries instead of building from source 2026-07-04 18:20:53 +07:00
cli release: v0.1.7 — password detection, Telex enabled, GNOME Wayland support 2026-07-01 11:00:11 +07:00
daemon fix: non-grabbed evdev on X11 — switch to XTest injection for instant correction 2026-07-04 18:20:53 +07:00
engine v0.1.19 2026-07-04 18:20:53 +07:00
NOTES feat: terminal VNI input — force VNI in terminals, remove from bypass_apps 2026-07-02 08:57:17 +07:00
packaging add installation and packaging scripts 2026-06-29 20:45:48 +07:00
protocol fix: X11 injector sends 'u' instead of backspace in paste_via_clipboard 2026-07-04 18:20:53 +07:00
scripts feat: add test VM setup script for Linux Mint/Ubuntu 2026-07-02 11:56:01 +07:00
ui v0.1.19 2026-07-04 18:20:53 +07:00
uinputd release: v0.1.7 — password detection, Telex enabled, GNOME Wayland support 2026-07-01 11:00:11 +07:00
web feat: add website as web/ subfolder 2026-07-04 17:18:22 +07:00
.gitignore release: v0.1.5 — Event Sourcing, Flatpak build fixes, icons 2026-06-28 21:20:19 +07:00
Cargo.toml fix: X11 key lookup, bamboo engine port, uinput injection overhaul 2026-06-26 15:20:03 +07:00
CHANGELOG.md docs: update changelog for distro support, roadmap, deps fixes 2026-07-01 17:07:40 +07:00
install.sh production: download prebuilt binaries instead of building from source 2026-07-04 18:20:53 +07:00
LICENSE Viet+ v0.1.0 - Vietnamese Input Method for Linux 2026-06-24 10:13:10 +07:00
Makefile release: v0.1.6 — uinput-first injection, window-switch fix, Telex disabled 2026-06-29 16:07:15 +07:00
README.md docs: announce terminal support in Features table + Configuration 2026-07-02 16:25:42 +07:00
uninstall.sh production: download prebuilt binaries instead of building from source 2026-07-04 18:20:53 +07:00
vietc.service Viet+ v0.1.1 2026-06-24 17:29:12 +07:00
vietc.toml fix: start_enabled=true by default, log daemon to file instead of /dev/null 2026-06-26 09:09:04 +07:00

Platform Rust License Version Tests Event Sourcing


Viet+

Vietnamese Input Method for Linux
Zero underline • No pre-edit buffer • Backspace-Replay sync • Built in Rust


What is Viet+?

Viet+ is a Vietnamese input method for Linux that takes a fundamentally different approach from every other IME: Direct Input.

Most Vietnamese IMEs use a pre-edit buffer — you type into a temporary buffer with an ugly underline, and the text only becomes real Vietnamese when you commit it. This causes duplicate text, underline distraction, broken copy/paste, and desync between the engine state and what's on screen.

Viet+ eliminates all of this. Keystrokes are instantly converted to Unicode — what you type is what you see. No buffer. No underline. No duplication.


Features

Feature How It Works
Direct Input No pre-edit buffer. Keystrokes instantly become text via uinput injection
VNI & Telex Both input methods fully supported, switchable at runtime via Ctrl+Shift
Bamboo Engine Transformation model — composition, marks, tones, flexible backtracking
Smart Clusters uo→ươ with backtrack, ua→ưa horn placement
Macro Expansion ko → không, dc → được, add your own
Casing Preservation Tieengs → Tiếng, TIEENGS → TIẾNG
App Memory Per-app Vietnamese/English state, saved to overrides.toml
Hot Reload Config changes apply without restart
Window-Switch Reset Engine clears automatically on Alt+Tab
CPU Priority Pinned to P-cores (0-3) + nice(-10) for low-latency input
Uinput Injection /dev/uinput for reliable injection on X11 and Wayland
Terminal Support Works in all major terminals: kitty, alacritty, gnome-terminal, konsole, foot, wezterm, st, urxvt, xterm
Password Auto-Detection 4 layers: AT-SPI2 → sudo process → window-title → window-class
Tray Icon Shows current mode: Red VN / Blue TLX / Gray EN
GNOME/Wayland Native GNOME Shell D-Bus integration

Input Methods

Both VNI and Telex are fully supported. Switch via Ctrl+LeftShift or the tray menu.

VNI

Key Result Example
1 á (sắc) a1á
2 à (huyền) a2à
3 ả (hỏi) a3
4 ã (ngã) a4ã
5 ạ (nặng) a5
6 â/ê/ô a6→â, e6→ê, o6→ô
7 ơ/ư o7→ơ, u7→ư
8 ă a8→ă
9 đ d9→đ

Telex

Key Result Example
s á (sắc) as→á
f à (huyền) af→à
r ả (hỏi) ar→ả
x ã (ngã) ax→ã
j ạ (nặng) aj→ạ
aa â aa→â
ee ê ee→ê
oo ô oo→ô
ow ơ ow→ơ
aw ă aw→ă
uw ư uw→ư
dd đ dd→đ
w ươ chuongw→chương

Key Bindings

Combo Action
Ctrl+Space Toggle Vietnamese ON/OFF
Ctrl+LeftShift Toggle VNI ↔ Telex

Password Detection

4-layer automatic detection. When a password field is detected, Vietnamese is automatically disabled:

Layer Method Detects
1 AT-SPI2 D-Bus (a11y role check) Password fields in accessible apps
2 Process tree (pstree) sudo / passwd in terminal
3 Window title keywords password, sudo in title
4 Window class matching pinentry, polkit, kwallet dialogs

Distro Support

Tier Distro Install Method Status
Supported Ubuntu, Debian, Linux Mint, Pop!_OS, elementary OS, Zorin, Neon apt (auto-detected) Tested, one-command install
Supported Fedora, RHEL, CentOS dnf (auto-detected) Tested, one-command install
Supported Arch, Manjaro pacman (auto-detected) Tested, one-command install
⚠️ Might support openSUSE, Solus, Void zypper/eopkg/xbps (manual) Package names may differ; run install.sh and install missing deps manually if it fails
Not supported NixOS, Alpine, Gentoo, others N/A No package manager entry — install deps manually, then cargo build --release

⚠️ Tray icon note: GNOME (Ubuntu) and Cinnamon (Mint) need a StatusNotifier watcher for the tray to appear:

  • Ubuntu: sudo apt install gnome-shell-extension-appindicator
  • Mint: pre-installed; works out of the box

Installation

One-Command Install

Works on all Supported distros above. The script auto-detects your package manager:

From GitHub (recommended):

git clone https://github.com/vndangkhoa/vietc.git /tmp/vietc \
  && cd /tmp/vietc && sudo ./install.sh

From Forgejo (self-hosted):

git clone https://git.khoavo.myds.me/vndangkhoa/vietc.git /tmp/vietc \
  && cd /tmp/vietc && sudo ./install.sh

The script installs dependencies, compiles, installs to /usr/bin/, sets up uinput udev rules, and adds your user to the input group.

After install: Log out and log back in, then launch vietc-tray from your application menu.

One-Command Uninstall

From GitHub:

curl -sSL https://raw.githubusercontent.com/vndangkhoa/vietc/main/uninstall.sh | sudo bash

From Forgejo:

curl -sSL https://git.khoavo.myds.me/vndangkhoa/vietc/raw/branch/main/uninstall.sh | sudo bash

Manual Build & Run

# Install dependencies
sudo apt install git curl build-essential pkg-config \
  libx11-dev libxtst-dev libevdev-dev libdbus-1-dev libwayland-dev wl-clipboard

# Enable accessibility (Ubuntu Wayland — for password detection)
gsettings set org.gnome.desktop.a11y.applications screen-reader-enabled true

# Build
git clone https://github.com/vndangkhoa/vietc.git
cd vietc
cargo build --release

# Run (Mint — no sudo needed for uinput)
./target/release/vietc

# Run (Ubuntu — needs sudo for keyboard grab)
sudo ./target/release/vietc

Configuration

Config file: ~/.config/vietc/config.toml or ./vietc.toml

input_method = "vni"            # "vni" or "telex"
toggle_key = "space"            # Ctrl+Space to toggle VN/EN
toggle_method_key = "shift"     # Ctrl+Shift to toggle VNI/Telex
start_enabled = true            # Vietnamese by default
grab = true                     # grab keyboard (evdev)

[password_detection]
enabled = true
check_atspi2 = true
check_window_title = true
title_keywords = ["password", "passphrase", "secret", "mật khẩu", "sudo"]
password_apps = ["pinentry", "pinentry-gtk-2", "pinentry-qt",
  "lxqt-sudo", "kdesudo", "gksudo",
  "polkit-gnome-authentication-agent-1",
  "kwallet", "gnome-keyring", "ssh-askpass"]

[app_state]
enabled = true
english_apps = ["code", "vim"]
vietnamese_apps = ["telegram", "discord", "firefox"]
bypass_apps = ["steam"]

### Terminal Usage

Viet+ works perfectly in terminals. When running inside a terminal (e.g., gnome-terminal, kitty), Vietnamese input is automatically enabled:

```toml
terminal_input_method = "vni"    # Automatically switch to VNI when running in a terminal app

Supported terminals: kitty, alacritty, gnome-terminal, konsole, foot, wezterm, st, urxvt, xterm

Type Vietnamese directly — no pre-edit buffer, no underline, no duplication. Just type VNI or Telex digits and see Unicode characters instantly! terminal_apps = ["kitty", "alacritty", "gnome-terminal", "konsole", "foot", "wezterm", "st", "urxvt", "xterm"] terminal_input_method = "vni"

[macros] ko = "không" dc = "được" vs = "với"


---

## Architecture

vietc/ ├── engine/ # Vietnamese composition engine (bamboo-core port) ├── protocol/ # Keyboard capture & injection │ ├── uinput_monitor.rs # /dev/uinput injection (primary) │ ├── x11_inject.rs # XTest injection (fallback) │ ├── x11_capture.rs # XRecord key capture │ └── wayland_im.rs # Wayland IM protocol (stub) ├── daemon/ # Main daemon process │ ├── main.rs # Event loops, grab, signal handling │ ├── config.rs # TOML config loader + hot reload │ ├── app_state.rs # Per-app VN/EN memory + password detection │ ├── password_detector.rs # AT-SPI2 D-Bus password field detection │ └── display.rs # X11/Wayland/compositor detection ├── ui/ # System tray icon (ksni) │ └── tray.rs # Tray with VN/TLX/EN mode display ├── cli/ # Interactive test harness └── uinputd/ # Privileged uinput socket daemon


---

## Roadmap

### v0.1.8
- Wayland input method protocol (`zwp_input_method_v2`) — eliminates clipboard + backspace race, fixes missing spaces permanently
- Event-based AT-SPI2 focus monitoring (subscribe to a11y focus events, no polling)

### v0.1.9
- GitHub Actions CI for automated .deb builds
- Flatpak re-add for immutable distros

---

## License

MIT License — see [LICENSE](LICENSE) for details.

---

<p align="center">
  <sub>Made with love for the Vietnamese Linux community</sub>
</p>