[2026-05-10] vboard: дока по виртуальной клавиатуре на HTPC Bazzite

This commit is contained in:
Alexey Martemyanov
2026-05-10 23:25:36 +06:00
parent fcf2707814
commit cc82a72e40
2 changed files with 179 additions and 0 deletions
+7
View File
@@ -48,3 +48,10 @@ WoL должен быть включён в BIOS/UEFI. Проверить нас
sudo ethtool enp<X> # смотреть Wake-on: g
sudo ethtool -s enp<X> wol g # включить
```
## Виртуальная клавиатура
Установлен **vboard** (fork mallexxx/vboard, ветка `htpc-bazzite-patches`).
Полная дока с патчами и известными проблемами: [[virtual-keyboard-bazzite]]
+172
View File
@@ -0,0 +1,172 @@
# Виртуальная клавиатура на HTPC (Bazzite KDE Wayland)
Связано: [[htpc]] | [[magic4pc-webos]]
## Контекст
**HTPC:** [[htpc]] (192.168.1.86, Bazzite, KDE Plasma 6, Wayland)
Задача: экранная клавиатура для редкого ввода текста без физической клавиатуры.
---
## Изученные варианты
### ❌ Maliit (официальная KDE клавиатура)
- Единственный officially supported OSK для KDE Wayland
- **Критический баг (upstream, не Bazzite):** появляется один раз, после скрытия повторно не открывается без `pkill maliit-keyboard && maliit-keyboard`
- На Bazzite desktop: опция Virtual Keyboard вообще отсутствует в Accessibility Settings
- Статус: **не пригоден для HTPC**
### ❌ Onboard
- Полнофункциональная клавиатура с modifier keys
- Работает через XWayland + uinput (`GDK_BACKEND=x11 onboard`)
- Не rpm-ostree пакет, требует `rpm-ostree install onboard` (layered package)
- Нет трея, нет интеграции с KDE Virtual Keyboard API
- Статус: **рабочий fallback, но хуже vboard**
### ✅ vboard (выбранное решение)
- Форк: [archisman-panigrahi/vboard](https://github.com/archisman-panigrahi/vboard) (оригинал mdev588/vboard заброшен/заархивирован)
- Наш форк с патчами: [mallexxx/vboard](https://github.com/mallexxx/vboard) ветка `htpc-bazzite-patches`
- Python + GTK3 + uinput backend
- Нативный Wayland на KDE Plasma, трей, регистрируется как Virtual Keyboard
---
## Установка на Bazzite
### Зависимости (pip, без rpm-ostree)
```bash
pip3 install python-uinput meson ninja
```
> `/dev/uinput` уже доступен через Steam ACL (`user:bazzite:rw-` через `steam-devices` udev rules) — sudo не нужен.
### Сборка и установка (user scope)
```bash
git clone https://github.com/mallexxx/vboard.git
cd vboard
git checkout htpc-bazzite-patches
meson setup builddir-user --prefix=$HOME/.local
meson compile -C builddir-user
meson install -C builddir-user
# Создаёт KWin rule автоматически
```
### Регистрация как KDE Virtual Keyboard
```bash
kwriteconfig6 --file kwinrc --group Plugins --key kwin_wayland_vkbd_plugin 'io.github.archisman-panigrahi.vboard'
kwriteconfig6 --file kwinrc --group Plugins --key VirtualKeyboardEnabled true
```
Проверить: System Settings → Input Devices → Virtual Keyboard → выбрать Vboard.
---
## Известные проблемы и решения
### ⚠️ Ввод не работает (NullInputBackend)
**Причина:** `python-uinput` из pip не имеет `KEY_LESS` (есть только в системном пакете).
UInputBackend падает при инициализации → fallback на NullInputBackend → нажатия игнорируются.
**Патч** (`vboard/input_backends.py`):
```python
# было:
"<": uinput.KEY_LESS,
# стало:
"<": uinput.KEY_102ND,
```
`KEY_102ND` — стандартный keycode для клавиши `<`/`>` на европейских раскладках, есть в pip-версии.
### ⚠️ Автопоказ/скрытие по фокусу поля не работает
**Причина:** vboard не реализует `zwp_input_method_v2` Wayland протокол.
KDE запускает его как процесс, но сигналы "show/hide" не передаются.
**Решение:** оставить как есть — клавиатура висит поверх, управление через трей.
### ⚠️ Русская раскладка вводит латиницу
**Причина:** vboard шлёт физические keycodes (KEY_Q и т.д.), система переводит по своей раскладке.
**Решение:** синхронизировать системную раскладку KDE через D-Bus при переключении (см. патчи ниже).
### ⚠️ Таскбар исчез при попытке закрепить иконку через kwriteconfig
**Причина:** неверный group path в `plasma-org.kde.plasma.desktop-appletsrc` → plasmashell упал.
**Решение:** `plasmashell --replace` через SSH.
**Правильный способ** закрепить иконку: правый клик на `^` → Configure System Tray → Entries → Virtual Keyboard → Always Shown.
---
## Кастомные патчи (ветка htpc-bazzite-patches)
### 1. Скрыть кнопку закрытия
`vboard/window.py`:
```python
# было:
self.header.set_show_close_button(True)
# стало:
self.header.set_show_close_button(False)
```
### 2. Кнопка переключения EN/RU в хедере
`vboard/window.py` — в `create_settings()` после ESC кнопки:
```python
self.lang_button = Gtk.Button(label=self.keyboard_layout.upper())
self.lang_button.connect("clicked", self.cycle_keyboard_layout)
self.lang_button.set_name("esc-button")
self.header.pack_start(self.lang_button)
```
Новые методы:
```python
def cycle_keyboard_layout(self, widget=None):
keys = [k for k, _ in KEY_LAYOUT_CHOICES]
idx = keys.index(self.keyboard_layout) if self.keyboard_layout in keys else 0
next_key = keys[(idx + 1) % len(keys)]
self.set_keyboard_layout(next_key)
self.lang_button.set_label(next_key.upper())
self.sync_system_layout(next_key)
def sync_system_layout(self, layout_key):
import subprocess
layout_map = {"en": "0", "ru": "1"}
index = layout_map.get(layout_key)
if index is None:
return
try:
subprocess.Popen([
"qdbus", "org.kde.keyboard", "/Layouts",
"org.kde.KeyboardLayouts.setLayout", index
], env=dict(__import__("os").environ,
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"))
except Exception:
pass
```
> Индексы `en=0, ru=1` соответствуют порядку раскладок в KDE: проверить через
> `qdbus --literal org.kde.keyboard /Layouts org.kde.KeyboardLayouts.getLayoutsList`
### 3. Только EN/RU раскладки
`vboard/constants.py`:
```python
KEY_LAYOUT_CHOICES = (
("en", "English (US)"),
("ru", "Russian"),
)
```
---
## Управление
```bash
# Запустить вручную (обычно KDE делает сам)
XDG_RUNTIME_DIR=/run/user/1000 WAYLAND_DISPLAY=wayland-0 \
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus \
python3 ~/.local/bin/vboard &
# Перезапустить
kill -9 $(pgrep -f vboard)
# KDE перезапустит автоматически через ~3 сек
# Проверить что backend работает
python3 -c "
import sys; sys.path.insert(0, '$HOME/.local/share/vboard')
from vboard.input_backends import UInputBackend
b = UInputBackend(); print('OK')
"
```