first commit
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
"""Бэкенд глобальных клавиш на библиотеке keyboard — целевой для Windows.
|
||||
|
||||
Перехватывает клавиши ГЛОБАЛЬНО (окно может быть свёрнуто) — именно то,
|
||||
что нужно отцу. Требования/ограничения библиотеки keyboard:
|
||||
- Windows: работает без админ-прав;
|
||||
- Linux: требует root (поэтому в разработке используем console-бэкенд);
|
||||
- проект библиотеки не развивается с 2020 — если на Windows появятся
|
||||
проблемы, заменяем на pynput (интерфейс KeyEvents менять не придётся).
|
||||
|
||||
Клавиши задаются в .env (HOTKEY_TALK / HOTKEY_STOP / HOTKEY_REPEAT);
|
||||
по умолчанию: space / esc / enter. Имена — как в библиотеке keyboard
|
||||
(numpad-клавиши подберём при настройке на Windows, напр. «num 0», «num enter»).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from .base import KeyEvents
|
||||
|
||||
|
||||
class KeyboardHookBackend:
|
||||
name = "keys"
|
||||
|
||||
def __init__(self, events: KeyEvents, talk: str = "num 0",
|
||||
stop_key: str = "esc", repeat: str = "enter",
|
||||
dialog: str = "space") -> None:
|
||||
self._events = events
|
||||
self._talk = talk
|
||||
self._stop_key = stop_key
|
||||
self._repeat = repeat
|
||||
self._dialog = dialog # ПРОБЕЛ: тумблер диалога
|
||||
self._started = False
|
||||
|
||||
def start(self) -> None:
|
||||
import keyboard # ленивый импорт: на Linux без root упадёт — см. console
|
||||
|
||||
if self._dialog and self._events.on_dialog_toggle:
|
||||
keyboard.add_hotkey(self._dialog, self._events.on_dialog_toggle, suppress=True)
|
||||
if self._talk:
|
||||
keyboard.on_press_key(self._talk, self._talk_press)
|
||||
keyboard.on_release_key(self._talk, self._talk_release)
|
||||
keyboard.add_hotkey(self._stop_key, self._events.on_stop, suppress=True)
|
||||
keyboard.add_hotkey(self._repeat, self._events.on_repeat, suppress=True)
|
||||
self._started = True
|
||||
|
||||
def stop(self) -> None:
|
||||
if self._started:
|
||||
import keyboard
|
||||
keyboard.unhook_all()
|
||||
self._started = False
|
||||
|
||||
# --- внутреннее ------------------------------------------------------
|
||||
def _talk_press(self, event) -> None: # noqa: ANN001
|
||||
# Библиотека шлёт повторные down-события при удержании; лишние вызовы
|
||||
# безопасны: машина состояний игнорирует on_talk_down в состоянии listening.
|
||||
self._events.on_talk_down()
|
||||
|
||||
def _talk_release(self, event) -> None: # noqa: ANN001
|
||||
self._events.on_talk_up()
|
||||
Reference in New Issue
Block a user