"Заключительный аккорд" - "отцепляемся" от скан-кодов
Как я уже говорил - не очень хорошо, когда "действия" назначаются прямо в описании клавиши (в файлах xkb_symbols).
Во всяком случае, при этом трудно распространить наше решение на случай, когда роль основного или дополнительного переключателей (или обоих) выполняет не одиночная клавиша, а комбинация клавиш.
Обычно "хорошим тоном" является - привязать "действия" к каким-нибудь сиволам (через "интерпретации"), а в описании клавиш использовать только символы.
Давайте проделаем это для любого из примеров, например, последнего.
Единственная проблема - надо подобрать подходящии символы. Дело в том, что брать коды обычных символов (даже "экзотических" - типа "умлаутов") не очень хорошо. Потому, что при нажатии клавиши XKB будет не только выполнять соответствующие "действия", но и выдавать в прикладную программу эти символы. А программа, соответственно, будет пытаться их напечатать.
К счастью, в наборе символов есть группа кодов, которые должны использоваться только для внутренних нужд XKB и игнорироваться прикладными программами. Вы можете найти их в файле {XROOT}/include/X11/keysymdef.h
их названия начинаются на XK_ISO_. Например,
XK_ISO_First_Group XK_ISO_First_Group_Lock XK_ISO_Last_Group XK_ISO_Prev_Group_Lock
и т.п.
Конечно, там нет символов из названия которых следует, что по этому символу "записать в locked group число 3". Но мы можем изменить семантику любого из символов (тем более, что и не для каждого из этих символов задана семантика в "конфигах" XKB).
Давайте сначала выясним - сколько нам надо символов. Для этого посчитаем - сколько у нас различных действий в описании обоих переключателей.
LockGroup(group=1) LockGroup(group=2) LockGroup(group=3) SetGroup(group=2)
Итого - 4 штуки.
Давайте подберем им символы. Конечно, можно взять любые из тех о которых говорилось выше. Но, чтобы лучше в них ориентироваться, подберем такие, чтобы их название хоть немного походили на соответствующие действия.
Обратите внимание, чтов названиях присутствуют - First_Group, Last_Group, Next_Group и Prev_Group.
Давайте считать, что для нашего случая
- First_Group - group=1
- Next_Group - group=2
- Last_Group - group=3
- для LockGroup(group=1) - ISO_First_Group_Lock
- для LockGroup(group=2) - ISO_Next_Group_Lock
- для LockGroup(group=3) - ISO_Last_Group_Lock
- для SetGroup(group=2) - ISO_Group_Lock
Тогда логично выбрать
Составим соответствующие "интерпретации". Напомню, что это нужно делать в файле типа xkb_compat и, соответственно, "приплюсовать" это файл к строчке в "полной" конфигурации, которая описывает именно xkb_compat
(а не xkb_symbols).
Итак, наша "добавка" к xkb_compat (не забудьте ее "приплюсовать" куда надо) -
xkb_compat { interpret ISO_First_Group_Lock { action=LockGroup(group=1); }; interpret ISO_Next_Group_Lock { action=LockGroup(group=2); }; interpret ISO_Last_Group_Lock { action=LockGroup(group=3); }; interpret ISO_Group_Lock { action=SetGroup(group=2); locking = True;};
group 2 = AltGr; group 3 = AltGr; };
(Последнии две инструкции, "по идее" не нужны, поскольку уже должны быть в "общей конфигурации". Но почему-то они иногда "теряются".)
А описание символов (в xkb_symbols) теперь будут выглядеть как
key <CAPS> { [ ISO_Next_Group_Lock ], [ ISO_First_Group_Lock ], [ ISO_Last_Group_Lock ] };
key <MENU> { [ ISO_Group_Lock ] };
Можно пробовать.
На этом наши эксперименты на тему переключателей не заканчиваются.
Дальше мы рассмотрим еще более сложный случай (и другие механизмы) -