Как стать автором
Обновить

Новый аналог Punto Switcher для linux: xswitcher

Время на прочтение 3 мин
Количество просмотров 52K
Прекращение поддержки xneur вызвало у меня определённые страдания в последние полгода (с появлением OpenSUSE 15.1 на моих десктопах: при включённом xneur окна теряют фокус и забавно мерцают в такт ввода с клавиатуры).

«А, блин, опять не в той раскладке начал набирать» — в моей работе встречается до неприличия часто. И позитива не добавляет.


В то же время, я (как инженер-конструктор) могу достаточно ясно сформулировать чего хочу. А хотел я (сначала от 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 должен запускаться с рутовыми правами:

chown root:root xswitcher
chmod +xs xswitcher

Обратите внимание: владельцем файла с suid должен быть root, т.к. кто владелец — в того suid и превратит при запуске.

Параноики (я не исключение) могут клонировать из 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(), CtrlSequence(), RepeatSequence(), SpaceSequence(). Спасибо nsmcan за внимательность: исправил в коде и здесь. С определённой вероятностью можно отхватить баги при замене.
    В этом месте я не знаю «как надо» и буду рад любым предложениям.
  • (О ужас) конкурентное использование каналов (keyboardEvents, miceEvents).

Заключение


Код — простейший процедурный. И туп как я. Так что, тешу себя надеждой что дописать желаемое сможет практически любой технарь. И данное изделие благодаря этому не сгинет без поддержки подобно большинству just-for-fun.

Удачи!
Теги:
Хабы:
+44
Комментарии 87
Комментарии Комментарии 87

Публикации

Истории

Работа

Go разработчик
122 вакансии

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн