«А, блин, опять не в той раскладке начал набирать» — в моей работе встречается до неприличия часто. И позитива не добавляет.
В то же время, я (как инженер-конструктор) могу достаточно ясно сформулировать чего хочу. А хотел я (сначала от Punto Switcher, а затем, спасибо Windows Vista, окончательно пересев на Linux, от xneur) ровно одного. Осознав, что на экране белиберда не в той раскладке (такое обычно случается в конце набора нового слова), топнуть по «Pause/Break». И получить то что печатал.
На данный момент изделие имеет оптимальное (с точки зрения меня) отношение функциональность/сложность. Пора делиться.
TL.DR
Дальше пойдут всякие технические подробности, поэтому сначала — ссылка «на потрогать» для нетерпеливых.
На данный момент захардкожено следующее поведение:
- «Pause/Break»: забивает (Backspace) последнее слово, переключает раскладку в активном окне (между 0 и 1) и набирает ещё раз.
- «Левый Ctrl без ничего»: переключает раскладку в активном окне (между 0 и 1).
- «Левый Shift без ничего»: включает в активном окне раскладку №0.
- «Правый Shift без ничего»: включает в активном окне раскладку №1.
С этого момента я планирую кастомизировать поведение. Без обратной связи — не интересно (меня и так устраивает). Полагаю, на Хабре найдётся достаточный процент аудитории с аналогичными проблемами.
N.B. Т.к. в текущей версии кейлоггер прикручивается к "/dev/input/", xswitcher должен запускаться с рутовыми правами:
chmod +xs xswitcher
Параноики (я не исключение) могут клонировать из GIT и собрать на месте. Примерно так:
go get "github.com/micmonay/keybd_event"
go get "github.com/gvalkov/golang-evdev"
### X11 headers for OpenSUSE/deb-based
zypper install libX11-devel libXmu-devel
apt-get install libx11-dev libxmu-dev
cd "x switcher/src/"
go build -o xswitcher -ldflags "-s -w" --tags static_all src/*.go
Автозапуск добавлять по вкусу (в зависимости от DE).
Работает, «каши не просит» (≈30 секунд CPU в сутки, ≈12 МБ в RSS).
Подробности
Теперь — подробности.
Весь репозиторий изначально был посвящён моему пет-проекту, а другой заводить — пока лень. Так что, всё свалено в кучу (просто по папкам) и накрыто AGPL («патент наоборот»).
Код xswitcher написан на golang, с минимальными вкраплениями C. Предполагается, что такой подход даст наименьшие трудозатраты (пока так и есть). Сохраняя возможность подключать недостающее посредством cgo.
По тексту разложены комментарии, откуда чего позаимствовал и зачем. Т.к. код xneur меня «не вдохновил», за отправную точку взял loloswitcher.
Использование "/dev/input/" имеет как свои плюсы (всё видно в т.ч. зажатую клавишу с автоповтором), так и минусы. Минусы такие:
- Автоповтор (события с кодом «2») не коррелирует с повтором с иксах.
- Не видно ввода через интерфейсы X11 (так например VNC работает).
- Нужен рут.
С другой стороны, можно подписываться на события X через «XSelectExtensionEvent()». Подсмотреть можно в коде xinput. Для go ничего подобного не нашёл, а черновая реализация дала с ходу сотню строчек C-кода. Пока отложил в сторону.
Вывод «обратно» пока сделан через прикручивание виртуальной клавиатуры. Спасибо автору keybd_event, но там слишком высокоуровневая абстракция и дальше придётся переделывать. У меня, например, правая Win-клавиша 3-й ряд выбирает. А обратно транслируется только левая Win.
Известные ошибки
- Ничего не знаем про «композитный» ввод (пример: ½). Прямо сейчас оно не нужно.
- Неверно воспроизводим правую Win. В моём случае ломает расстановку акце́нтов.
- Нет внятного разбора ввода. Вместо этого — несколько функций: Compare(), CtrlSeqence(), RepeatSeqence(), SpaceSeqence(). С определённой вероятностью можно отхватить баги при замене.
В этом месте я не знаю «как надо» и буду рад любым предложениям. - (О ужас) конкурентное использование каналов (keyboardEvents, miceEvents).
Заключение
Код — простейший процедурный. И туп как я. Так что, тешу себя надеждой что дописать желаемое сможет практически любой технарь. И данное изделие благодаря этому не сгинет без поддержки подобно большинству just-for-fun.
Удачи!
Специально для сайта ITWORLD.UZ. Новость взята с сайта Хабр