Припинення підтримки xneur викликало у мене певні страждання за останні півроку (з появою OpenSUSE 15.1 на моїх десктопах: при включеному вікні xneur втрачають фокус і смішно мерехтять у такт введення з клавіатури).
"А, млинець, знову не в тій розкладці почав набирати" - в моїй роботі зустрічається до непристойності часто. І позитиву не додає.
У той же час, я (як інженер-конструктор) можу досить чітко сформулювати чогось хочу. А хотів я (спочатку від Punto Switcher, а потім, дякую Windows Vista, остаточно пересівши на Linux, від xneur) рівно одного. Усвідомивши, що на екрані біліберда не в тій розкладці (таке зазвичай трапляється в кінці набору нового слова), тупнути по Pause / Break. І отримати те, що друкував.
На даний момент виріб має оптимальне (з погляду мене) відношення функціональність/складність. Час ділитися.
Pause/Break: забиває (Backspace) останнє слово, перемикає розкладку в активному вікні (між 0 і 1) і набирає ще раз.
"Лівий Ctrl без нічого": перемикає розкладку в активному вікні (між 0 та 1).
"Лівий Shift без нічого": включає в активному вікні розкладку №0.
"Правий Shift без нічого": включає в активному вікні розкладку №1.
З цього моменту я планую кастомізувати поведінку. Без зворотного зв'язку – не цікаво (мене і так влаштовує). Вважаю, на Хабрі знайдеться достатній відсоток аудиторії з аналогічними проблемами.
NB Т.к. у поточній версії кейлоггер прикручується до "/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.