Прекратяването на поддръжката на 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 при стартиране.
Параноиците (аз не съм изключение) могат да клонят от и да компилират на място. Примерно така:
go get "github.com/micmonay/keybd_event"
go get "github.com/gvalkov/golang-evdev"
### X11 заглавия за OpenSUSE/deb-базирани
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 не ме вдъхнови, взех за отправна точка .
Използването на "\/dev\/input\/" има както плюсове (всичко се вижда, включително натиснат клавиш с автоповтор), така и минуси. Минусите са следните:
- Автоповторът (събитията с код «2») не корелира с повторите в X.
- Не се вижда входът през интерфейсите X11 (например VNC работи по този начин).
- Нужен е root.
От друга страна, можем да се абонираме за събития X чрез "XSelectExtensionEvent()". Може да се погледне в . За go не намерих нещо подобно, а черновата реализация извади от раз сто реда C-код. Засега го отложих настрана.
Изходът "обратно" за момента е реализиран чрез добавяне на виртуална клавиатура. Благодаря на автора на keybd_event, но там е прекалено високоефективна абстракция и след това ще трябва да се преизгради. Например, при мен дясната клавиша Win от третия ред избира. А обратно се транслира само лявата Win.
Известни грешки
- Нищо не знаем за "композитния" вход (пример: ½). В момента не е необходимо.
- Неправилно възпроизвеждане на дясната Win. В моя случай разваля разположението на акцентите.
- Няма ясен анализ на входа. Вместо това — няколко функции: Compare(), CtrlSequence(), RepeatSequence(), SpaceSequence(). Благодаря за вниманието: поправих в кода и тук. С определена вероятност могат да се вземат бъгове при заместване.
На това място не знам "как трябва" и ще се радвам на всякакви предложения. - (О ужас) конкурентно използване на канали (keyboardEvents, miceEvents).
Заключение
Кодът — най-прост процедурен. И глупав като мен. Така че, тешу се с надеждата, че желаното ще може да напише практически всеки техник. И това изделие благодарение на това няма да изчезне без подкрепа, подобно на повечето just-for-fun.
Успех!
Източник: habr.com
