An on-screen keyboard for Linux that aims to mimic physical keyboard behavior as closely as possible.
📘 Chinese documentation: README.zh-CN.md
QingBoard is a GTK3 virtual keyboard that injects real key events through uinput. It is designed for touch devices, temporary keyboard replacement, and accessibility-oriented desktop workflows.
Compared with simpler virtual keyboards, QingBoard focuses on:
- Modifier-key semantics
- Shortcut usability
- State synchronization (e.g., CapsLock indicator)
- Multi-touch support (independent touch point tracking)
- Hardware-like modifier behavior
- Supports Shift/Ctrl/Alt/Super press/release handling.
- Supports one-shot/latch behavior for modifiers (e.g., tap Shift once to lock it).
- Shortcut friendly
- Combination keys can be sent to the focused window (e.g.,
Ctrl+C,Ctrl+V).
- Combination keys can be sent to the focused window (e.g.,
- Double-Shift shortcut trigger
- Double tapping either Shift key emits a configurable shortcut (default:
LEFTSHIFT,SPACE). Can be enabled/disabled via config.
- Double tapping either Shift key emits a configurable shortcut (default:
- Fast sequential taps
- Regular keys are emitted on press (tap-first strategy), so quick consecutive taps remain reliable even in single-pointer touch stacks (common with XWayland).
- Global top-layer window
- Keeps minimize/maximize/close decorations, uses NORMAL window type (with draggable titlebar) and repeatedly raises itself with sticky + keep-above hints to reduce IME overlap risk.
- Long-press repeat
- Regular keys repeat while held (delay 420ms, interval 70ms).
- Space cursor mode
- Long-press Space to enter cursor mode; the key label changes to
◀ Space ▶with a highlighted border and text. - Slide horizontally to send Left/Right; slide vertically to send Up/Down.
- Trigger threshold adapts dynamically to sliding speed for more natural control.
- Long-press Space to enter cursor mode; the key label changes to
- CapsLock handling
- CapsLock key toggles internal state, sends the key event, and updates the header indicator.
- Header indicator is a button‑style label matching other controls; it turns accent‑colored when CapsLock is on.
- CapsLock state is saved and restored on next launch.
- Dynamic key labels with Shift
- Symbol keys update labels while Shift is active (e.g.,
1→!).
- Symbol keys update labels while Shift is active (e.g.,
- Multi-touch support
- Each touch point is tracked independently, allowing multiple keys to be pressed simultaneously without interference.
- Touch motion is used for Space cursor mode, enhancing the touchpad experience.
- Customizable UI
- Themes:
Dark,Light,Midnight - Reduced key opacity for better readability of background content when using translucent themes.
- Hover/prelight does not alter key background opacity; only click feedback and latched states change visuals.
- Adjustable opacity and font size from header controls.
- Themes:
- Persistent settings
- Saves theme, opacity, font size, window size, double‑Shift shortcut, and CapsLock state.
Required runtime components:
- Linux
- Python 3.9+
- GTK 3 via PyGObject (
python3-gi/python3-gobject) uinputkernel module + Python binding (python3-uinput/python-uinput)
Optional but useful on some distros:
steam-devices(helps input‑device permissions in some environments)
sudo apt install python3-gi python3-uinput steam-devicessudo dnf install python3-gobject python3-uinput steam-devicesyay -S python-uinput steam-devicespython3 qingboard.pymkdir -p ~/.local/share/applications/
cat > ~/.local/share/applications/qingboard.desktop <<EOF
[Desktop Entry]
Exec=bash -c 'python3 /path/to/qingboard.py'
Icon=preferences-desktop-keyboard
Name=QingBoard
Terminal=false
Type=Application
Categories=Utility;
NoDisplay=false
EOF
chmod +x ~/.local/share/applications/qingboard.desktopConfig file:
~/.config/qingboard/settings.conf
Example:
[DEFAULT]
theme = Dark
opacity = 0.96
font_size = 18
width = 0
height = 0
double_shift_shortcut_enabled = true
double_shift_shortcut = LEFTSHIFT,SPACE
capslock_on = falseSettings notes:
theme:Dark/Light/Midnightopacity: clamped by app (about0.35to1.0)font_size: clamped by app (about10to48)width/height: persisted window sizedouble_shift_shortcut_enabled: enable/disable double‑Shift shortcut (trueby default)double_shift_shortcut: comma‑separated key tokens (e.g.,LEFTSHIFT,SPACE)capslock_on: internal CapsLock state (saved automatically)
-
Error:
no such deviceuinputmodule may not be loaded:sudo modprobe uinput
-
Stops working after reboot
Enable module autoload:
echo 'uinput' | sudo tee /etc/modules-load.d/uinput.conf
-
Permission denied for key injection
Reload udev rules and re‑log in:
sudo udevadm control --reload-rules && sudo udevadm trigger -
steam-devicespackage not found (Fedora, etc.)Ensure related repositories are enabled (for Fedora, RPM Fusion is commonly required).
-
Desktop/compositor compatibility differences
Input injection behavior may vary depending on distro, desktop environment, and compositor implementation. On XWayland in particular, multi‑touch pointer semantics can differ from native Wayland, so gesture‑style interactions may be interpreted as single‑pointer sequences.
Contributions are welcome.
Before opening a PR, please:
- Keep
README.md(EN) andREADME.zh-CN.md(ZH) consistent. - Explain motivation, behavior changes, and potential risks.
- Attach screenshots/recording for UI behavior changes.
- Update configuration/troubleshooting docs if config behavior changes.
This project was originally inspired by vboard. We thank the author for the early ideas. After a complete rewrite, QingBoard has evolved independently and now differs significantly in both code and functionality.
This project is licensed under GNU LGPL v2.1. See LICENSE.