- install.sh: rewritten to download prebuilt tarball from GitHub releases (or fallback to .deb extraction), removing verbose cargo build output - release.yml: new CI workflow to build & upload tarball on tag push - uninstall.sh: add systemctl --global daemon-reload after removing service - daemon/src/main.rs: fix VNI backspace offset in X11 keymap capture path (missing +1 adjustment for control keys that reach the app directly) |
||
|---|---|---|
| .github/workflows | ||
| cli | ||
| daemon | ||
| engine | ||
| NOTES | ||
| packaging | ||
| protocol | ||
| scripts | ||
| ui | ||
| uinputd | ||
| web | ||
| .gitignore | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| install.sh | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| uninstall.sh | ||
| vietc.service | ||
| vietc.toml | ||
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>