ENGLISH | KOI | WIN | ALT | ISO
Мои программы

Описание "действий".

Описание "действий" (actions) используются в файлах типа xkb_symbols, где они "привязываются" к скан-кодам клавиш, и в файлах типа xkb_compat, где они "привязываются" к управляющим символам. (Напомню, что в xkb_compat, описываются "интерпретации" - таблички, которые помогают менять привязку "действия" к скан-кодам, когда прикладные программы меняют привязку соответствующих "управляющих символов").

Описание действия похоже на объявление функции в языке C, то есть

имя_действия '(' список_аргументов ');'

Но отличие в том, что в списке аргументов указываются не просто значения, а пары имя-значение:

имя_аргумента '=' значение_аргумента

Например

MovePointer(x=10, y=10, repeat=False);

Кстати программа xkbcomp, которая компилирует файлы конфигурации, во многих случаях понимает разные названия для одного и того же действия и разные имена для одного и того же аргумента.

Внутри XKB действия представляют собой некую структуру которая содержит

  • код (номер) действия;
  • поле битовых флагов, которые как-то модифицируют выполняемое действие;
  • поля содержащие аргументы действия (их может быть несколько или вообще ни одного)

Понятно, что количество и смысл аргументов зависит от конкретного действия. А вот флаги у многих действий совпадают по названию и по смыслу. При этом надо заметить, что в файлах конфигурации не все флаги можно указать явно.

Например некоторые действия имеют аргументы, которые могут быть как абсолютными значениями, так и приращениями к текущим значениям. Это могут быть координаты курсора на экране, номер группы XKB и т.п. Во внутренней структуре действия для различения этих двух типов аргументов предусмотрен специальный флаг Absolute. Но в описаниях функций он явно не указывается. О том какие значения вы имели ввиду (абсолютные или относительные) XKB догадывается по наличию знака "+" или "-" перед значением аргумента.
То есть

SomeAction(x=10, y=10)

означает абсолютные значения для x и y, а

SomeAction(x=+10, y=+10)

означает положительные приращения для тех же переменных.

Другой пример неявных флагов это флаги, которые указывают - в какой момент выполнять действие - при нажатии клавиши или при ее отпускании. Такие флаги есть почти у каждого действия, хотя во многих случаях они не имеют особого смысла (например, какая вам разница когда установится модификатор CapsLock - в момент нажатии соответствующей клавиши или при ее отпускании).

Эти флаги в описаниях действий или вообще нельзя указать, или это указание делается через некий "псевдоаргумент" (в том смысле, что он не соответствует никакому полю во внутренней структуре XKB описывающей действие).
(У вас может возникнуть вопрос - зачем вообще существуют флаги, которые никак нельзя задать в описании? Дело в том, что в XKB протоколе существуют специальные запросы к серверу, которые позволяют загрузить или модифицировать любое действие из прикладной программы. Вот они то не накладывают никаких ограничений и позволяют задать любые флаги, имеющие смысл для данного действия.)

И еще несколько слов о том, как в описании действия указываются флаги. Хотя они предствляют собой отдельные биты в одном и том же поле внутренней структуры XKB, но в описании указываются как отдельные переменные типа boolean (то есть, их значением может быть только "да" или "нет"). При этом xkbcomp понимает в качестве значений логической переменной и другие слова - в качестве "да" вы можете писать yes, on, true, а качестве "нет" - no, off, false.

Но и это еще не все. Специально для логических переменных предусмотрена еще более простая запись. Вы можете написать просто имя переменной (флага) безо всякого значения и знака присваивания, это будет означать, что соответствующая переменная имеет значение "да". А вот если перед именем переменной поставить знак "!" или "~", это будет означать, что переменная имеет значение "нет".

Например следующие строчки полностью эквивалентны

SomeAction(..., SomeFlag=yes, ...); SomeAction(..., SomeFlag=on, ...); SomeAction(..., SomeFlag=true, ...); SomeAction(..., SomeFlag, ...);

и следующие строчки тоже эквивалентны

SomeAction(..., SomeFlag=no, ...); SomeAction(..., SomeFlag=off, ...); SomeAction(..., SomeFlag=false, ...); SomeAction(..., !SomeFlag, ...); SomeAction(..., ~SomeFlag, ...);

Но учтите, что каждый флаг имеет значение по умолчанию. Поэтому в большинстве случаев их вообще не указывают, если нужное значение совпадает с "умолчательным".

Действия, изменяющие состояние XKB.

Напомню, что в состояние XKB входят - текущий набор модификаторов, текущий номер группы и "набор управляющих флагов" (XKB Controls).
Причем и набор модификаторов и номер группы распределены по трем переменным, значение которых может меняться независимо. Поэтому существует три действия для изменения модификаторов (каждое действие меняет свою переменную) и три действия для изменения номера группы.

Изменение набора модификаторов (modifiers).

Как я уже сказал, набор модификаторов распределен по трем переменным - base modifiers, latched modifiers и locked modifiers.
Соответственно действия для их изменения:

  • SetMods - меняет base modifiers,
  • LatchMods - меняет latched modifiers,
  • LockMods - меняет locked modifiers.

Основной аргумент у всех трех действий - modifiers (другое имя - mods). А его значение - название виртуального или реального модификатора. Если одно действие меняет сразу несколько модификаторов, их можно перечислить через знак "+". Например

SetMods(mods=Shift+Control);

Вместо названия модификатора можно указать специальное значение UseModMapMods (или просто ModMapMods). Это будет означать, что сами модификаторы надо взять из списка виртуальных модификаторов, связаных с этой клавишей (modmap и vmodmap).

Надо также заметить, что эти три действия отличаются не только тем, какую переменную они меняют. Они по разному работают в момент нажатия и в момент отпускания клавиши. Вспомните как отличается работа клавиш Shift и CapsLock. Первая должна действовать только пока ее удерживают в нажатом состоянии, то есть при ее нажатии модификатор Shift должен появиться, а при отпускании - автоматически исчезнуть. А вот CapsLock должна действовать долговременно - при первом нажатии ее модификатор должен стать активным и оставаться в таком состоянии даже после того как вы отпустите клавишу. А вот по повторному нажатию/отпусканию - убраться.

Так вот. Первые два действия предназначены для модификаторов типа Shift. То есть когда клавиша с таким действием нажимается, модификатор, указанный в аргументе добавляется в соответсвующую переменную (base или latched), а при отпускании клавиши то же действие выполняет обратную операцию - убирает модификатор.

А вот действие LockMods при первом исполнении только добавляет модификатор в locked modifiers, но не удаляет его при отпускании клавиши, а вот если модификатор уже установлен (то есть это уже повторное нажатие то же клавши), то при нажатии клавиши модификатор наоборот - убирается из locked modifiers.

Обратите внимание, что на самом деле совсем необязательно, чтобы вы использовали для модификатора Shift действие типа SetMods, а для модификатора Lock - LockMods. Вы можете "залокировать" Shift или наоборот - делать Lock активным только на время удержания клавши. Но это уже зависит от того, что вы собственно хотите этим добится. :-)

Также поведение первых двух действий могут слегка изменяться с помощью двух флагов - clearLocks и latchToLock.

Поэтому полное описание всех деталей этих действий выглядит так

Действие При нажатии При отпускании
SetMods Добавляет модификаторы в base modifiers
  • Убирает свои модификаторы из base modifiers
  • если clearLocks=yes и между нажатием и отпусканием этой клавиши вы не нажимали другие клавиши, то эти же модификаторы вычищаются и из locked modifiers
LatchMods Добавляет модификаторы в latched modifiers
  • Убирает свои модификаторы из latched modifiers
  • если clearLocks=yes и между нажатием и отпусканием этой клавиши вы не нажимали другие клавиши, то эти же модификаторы вычищаются и из locked modifiers
  • если latchToLock=yes, то те же модификаторы запоминаются в locked modifiers
LockMods
  • Добавляет модификаторы в base modifiers
  • если этих модификаторов нет в locked modifiers, то добавляет их туда, в противном случае наоборот - убирает
  • Убирает свои модификаторы из base modifiers
  • locked modifiers не меняется.

Изменение номер группы.

Так же как и набор модификаторов, номер группы "размазан" по трем переменным - base group, latched group и locked group. Для получения реального или действующего номера группы значения этих переменных складываются. Если получившаяся сумма выходит за допустимые границы (количество групп реально существующих в раскладке клавиатуры) она выравнивается по одному из трех алгоритмов. Кстати и значения каждой из трех переменных тоже выравниваются по тому же алгоритму при каждом изменении переменной.

Дествия меняющие номер группы очень похожи на действия меняющие набор модификаторов:

  • SetGroup - меняет base group
  • LatchGroup - меняет latched group
  • LockGroup - меняет locked group

Понятно, что аргументом этих действий будет не список модификаторов, а номер группы - group. Но главное отличие не только в этом, а в том, что номер группы может быть как абсолютным значением, так и приращением к текущему значению соответсвующей переменной (приращение может быть и отрицательным).

Как я уже объяснял выше, для того, чтобы xkbcomp понял, что вы имеете ввиду приращение, а не абсолютное значение, значение аргумента должно быть указано с знаком "+" или "-". Например

  • LockGroup(group=1) записать в locked group первую группу.
  • LockGroup(group=+1) увеличить значение locked group на единицу.
  • LockGroup(group=-1) уменьшить значение locked group на единицу.

Так же как и действия для изменения модификаторов эти действия отличаются по своему эффекту в момент нажатия и отпускания клавиши. SetGroup и LatchGroup при нажатии заносят соответствующее значение в свою переменную а при отпускании клавиши - очищают ее.

Кстати заметьте, что номер группы меняется в пределах от 1 до 4 и не бывает нулевым. Поэтому там где говориться, что переменная "очищается" на самом деле надо понимать - устанавливается значение "группа 1".

Поведение LockGroup несколько отличается от LockMods - она только заносит (или добавляет) нужное число в locked group при нажатии, но никогда не очищает ее. Поэтому, если вам надо, чтобы последовательные нажатия клавиши с действием LockGroup перебирали группы, используйте "добавки", а не абсолютные значения.
Напомню, что после увеличения или уменьшения переменной locked group ее значение корректируется так, чтобы оно попадало в допустимый диапазон. Поэтому если у вас в раскладке клавиатуры две группы, и текущее значение locked group "группа 2", то при добавлении единицы XKB получившийся номер выдет за пределы допустимого и XKB "завернет" его обратно, так что получится "группа 1". Ну а при добавлении единицы к "группа 1" получится "группа 2" без всяких дополнительных трюков. Так что действие

LockGroup(group=+1);

будет успешно переключать группы (первую во вторую и наоборот) в любом состоянии.

Первые два действия так же как и {Set,Latch}Mods могут иметь флаги clearLocks и latchToLock.

Полное описание этих действий в таблице.

Действие При нажатии При отпускании
SetGroup заносит значение аргумента и добавляет приращение в переменную base group
  • отнимает приращение или абсолютное значение от base group
  • если clearLocks=yes и между нажатием и отпусканием этой клавиши никакие другие не нажимались, то очищается locked group.
LatchGroup заносит значение аргумента и добавляет приращение в переменную latched group
  • отнимает приращение или абсолютное значение от latched group
  • если clearLocks=yes и между нажатием и отпусканием этой клавиши никакие другие не нажимались, то очищается locked group.
  • если latchToLock=yes, к locked group добавляется то же значение, что вычитается из latched group.
LockGroup заносит значение аргумента или добавляет приращение к locked group ничего не меняется.

Изменение управляющих флагов (XKB Controls).

Набор управляющих флагов в отличии от набора модификаторов или номера группы существует только в одном экземпляре.

Поэтому для изменения этого набора существуют только два действия - SetControls и LockControls. Они работают с одним и тем же набором, но как понятно из названий, первая устанавливает флаги при нажатии клавиши и убирает при отпускании, а вторая - при первом нажатии/отпускании только устанавливает флаги, а убирает их при повторном нажатии клавиши с тем же действием.

Аргумент у этих действий называется controls или ctrls.
Если в одном действии нужно изменить несколько controls, они перечисляются через знак "+".

Флагов у этих действий нет.

Список "управляющих флагов", которые можно менять этими действиями:

  • RepeatKeys, или Repeat, или AutoRepeat - включение автоповтора для всех клавиш (по умолчанию он включен)
  • AccessXKeys - включение распознавания "магических последовательностей" AccessX.
  • SlowKeys - режим SlowKeys
  • BounceKeys - режим BounceKeys
  • StickyKeys - режим StickyKeys
  • AccessXTimeout - режим выключения AccessX по таймауту.
  • AccessXFeedback - "дополнительная звуковая индикация" различных режимов AccessX
  • MouseKeys - включение режима эмуляции событий мыши
  • MouseKeysAccel - режим движения "с ускорением" курсора мыши (имеет смысл только при включеном MouseKeys)
  • Overlay1 - включить первую группу перекрытий
  • Overlay2 - включить вторую группу перекрытий
  • AudibleBell - включить "пищалку" (по умолчанию включена). Напомню, что XKB может вместо обычного "писка" посылать специальные event'ы приложениям. Если этот режим используется, то обычную "пищалку" имеет смысл выключить.
  • IgnoreGroupLock - управляет содержимым клавиатурных event в режиме GrabKey. Если этот флаг установлен, то в event'ах не указывается содержимое locked group.
  • all - установить все управляющие флаги
  • none - никаких управляющих флагов

Действие ISO_Lock.

Называется: ISOLock.
Это действие является дополнительным к перечисленным выше. Она служит для изменения действия других клавиш - превращает их из обычных в "локирующиеся".

То есть вы можете нажать ISO_Lock и удерживая ее нажатой нажать какую-нибудь из клавиш c действиями типа SetMods, SetGroup, SetControls или PointerButton (смотри ниже) при этом их действие меняется на LockMods, LockGroup, LockControls или LockPointerButton соответственно.

Основной аргумент: affect. Он позволяет отфильтровать действия, подлежащие изменению. Его возможные значения:

  • modifiers или mods - может менять {Set,Latch}Mods на LockMods.
  • groups или group - может менять {Set,Latch}Group на LockGroup.
  • controls или ctrls - может менять SetControls на LockControls.
  • pointers или ptr - может менять PointerButton на LockPointerButton.
  • all - все перечисленные выше.
  • none - никакие.
Естественно вы можете в качестве значения указать любую комбинацию из этих слов (через знак "+"). По умолчанию affect=all.

Также это клавиша (клавиша с таким действием) может использоваться и отдельно, не в комбинации с другими. В таком качестве она может менять группу или модификатор(ы), но несколько необычным образом. Ее эффект зависит от того, была ли нажата какая-нибудь клавиша между ее нажатием/отпусканием.

Если она служит для изменения группы, то ...

  • во-первых у нее должен быть аргумент group
  • при нажатии значение аргумента заносится в base group
  • а действие про отпускании может быть разным
    • если после ее нажатия вы нажимали другие клавиши (например буквенные), то при отпускании номер группы просто убирается из base group. То есть изменение группы будет временным как при выполнении SetGroup.
    • а если никаких других клавиш вы не нажимали (просто нажали и отпустили клавишу с действием ISOLock), то значение аргумента будет перенесено в locked group. То есть в этом случае она работает как LockGroup.

Аналогичные действия выполняются если эта клавиша служит для изменения каких-либо модификаторов:

  • в аргументах должны быть указаны modifiers (или mods)
  • при нажатии эти модификаторы добавляются в base modifiers
  • при отпускании ...
    • если нажимались другие клавиши, то модификаторы просто убираются из base modifiers как при выполнении SetMods.
    • если нажатий других клавиш не было, то модификаторы убираются из base modifiers, но добавляются в locked modifiers, как при выполнении LockMods.

Итак. Возможные аргументы: affect, group, modifiers (mods).
При этом group и modifiers взаимоисключающие. Вообще без аргументов это действие аналогично

ISOLock(modifiers=Lock, affect=all);

Дополнительных флагов нет (на самом деле флаги есть, но их значение неявно задается вашеперечисленными аргументами).

Действия для эмуляции событий мыши

Движение курсора

Название действия: MovePtr или MovePointer.
Аргументы: координаты x и y.
Это как раз одно из тех действий, где аргументы могут означать как абсолютное значение, так и приращение к текущему значению. Напомню, что для указания относительных значений надо перед значением аргумента поставить знак "+" или "-". Обратите внимание, что

MovePtr(x=+10, y=0);

будет означать - увеличить координату x на 10 точек, а y сделать равным нулю (то есть переместить указатель на самый верхний ряд точек).
А для того, чтобы указатель переместился по x на десять точек, но не менял y координату, надо писать

MovePtr(x=+10, y=+0);

У этого действия есть только один флаг - accel (другие его названия - accelerate или repeat). Для того, чтобы понять его смысл надо вспомнить, что существует два режима движения курсора - простой и ускоренный (accelerated).

Так вот этот флаг позволяет отключить ускорение при выполнении этого действия, но не наоборот. То есть если в текущий момент включен обычный неускоренный режим движения, то значение этого флага ничего не меняет. И только если включен режим ускорения, то с помощью этого флага можно выполнить движение без ускорения.

Поскольку этот флаг "отменяющий" некоторый режим, то по умолчанию его значение yes. А указывать его в описании нужно только в том случае, если ван нужно значение no.

Нажатие кнопок мыши

Это действие называется PtrBtn или PointerButton.
Аргументы: номер кнопки - button и число повторов - count.
Номер кнопки можно задавать просто целым числом (1-5) или "названием кнопки" - button1, button2 ... button5.

Счетчик повторов является необязательным аргументом и нужен только если вам надо одним нажатием клавиши изобразить "двойной клик" (или тройной, четверной и т.д.). Значение аргумента count - положительное целое.

Кроме того, в качестве номера кнопки можно указать слово default.
Напомню, что в XKB есть понятие "кнопка по умолчанию", конкретное значение которой меняется другим действием. А в этом действие просто указывается, что нажимается та кнопка, номер которой запомнен в качестве "кнопки по умолчанию".

Флагов у этого действия нет.

Нажатие и удержание кнопки мыши

Называется: LockPtrBtn, или LockPointerButton, или LockPtrButton, или LockPointerBtn.

Это действие несколько отличается от предыдущего.
Вы конечно знаете, что для выполнения некоторых операций с помощью мыши (например - выделение текста) надо нажать кнопку мыши и не отпуская ее двигать мышь. При эмуляции событий мыши с помощью клавиатуры это означает, что вы должны нажать клавишу эмулирующую нажатие мышинной кнопки и удерживая ее манипулировать несколькими другими клавишами двигающими курсор. Это не всегда удобно, особенно если для эмуляции используются не одиночные клавиши, а комбинации (например Shift+стрелка).

Поэтому в XKB предусмотрены действия которые позволяющие нажимать кнопки "с удержанием". То есть, в отличии от предыдущего действия, которое по нажатию клавиши изображает нажатие кнопки а при отпускании клавиши отпускание кнопки, эти действия работают как клавиши CapsLock или NumLock.
То есть первое нажатие/отпускание клавиши только нажимает кнопку мыши и оставляет ее в нажатом состоянии, а повторное нажатие/отпускание клавиши генерируетя событие "отпускание кнопки мыши".

(На самом деле внутри XKB и это и предыдущее дествия имеют один и тот же код действия и отличаются только одним флагом.)

Аргументы в основном те же, что и для предыдущего действия button и count. (Хотя я не представляю себе - зачем в этом случае нужен count). Так же как и в предыдущем случае button может ссылыться на default button.

Но есть еще один дополнительный аргумент (необязательный) - affect. С его помощью можно указать, что это действие будет только нажимать кнопку или наоборот - только "отжимать" ее. То есть вы можете нажатие и отпускание кнопки разнести по разным клавишам (естественно действия на этих клавишах будут с разным значением affect).

Значение аргумента affect может быть одно из слов:

  • lock - только нажимать и фиксировать кнопку (повторные нажатие клавиши не отжимают кнопку);
  • unlock - только отжимать кнопку (если она не нажата, то это действи не нажмет ее);
  • both - первое нажатие клавиши нажимает и фиксирует кнопку, повторное нажатие той же клавиши отпускает кнопку; это режим по умолчанию;
  • neither - не нажимать и не отжимать кнопку (Забавно. Конечно действие с таким значением affect смысла не имеет.)

Определение "кнопки по умолчанию".

Называется: SetPtrDflt или SetPointerDefault.
Основной аргумент: номер кнопки - button.
Это действие запоминает - какая кнопка мыши в данный момент является "кнопкой по умолчанию" (напомню, что действия, нажимающие кнопку могут своим аргументом ссылаться на эту кнопку).

Заметьте, что это действие позволяет как указать точное (абсолютное) значение номера кнопки, так и относительное изменение номера. В последнем случае номер кнопки должен быть числом со знаком "+" или "-".

Понятно, что если при увеличении или уменьшении текущего значения получится номер выходящий за пределы допустимых номеров, XKB "завернет" его в допустимый диапазон. Таким образом вы можете одной клавишей перебирать номера кнопок циклически, делая их по очереди default button.

Это действие может иметь еще один аргумент - affect.
Но допустимым для него является только одно значение (хотя названий у этого значения несколько - Button, DefaultButton, DfltBtn), оно же - значение по умолчанию. Поэтому указывать его нет никакой необходимости, хотя в некоторых существующих файлах вы можете его встретить.

Другие действия.

Посылка сообщения.

XKB позволяет генерировать свои специальные сообщения (event) вместо (или вместе с) обычного сообщения о нажатии/отпускания клавиши.
Программа, которая хочет получать такие сообщения должна сказать об этом серверу с помощью специального запроса.
Такое сообщение кроме обычных атрибутов любого event'а (тип event'а, Display, time и т.д.) включает в себя 6 байт произвольных данных, которые задаются в описании действия и интерпретируются программой, получившей event.

Итак. Для генерации таких сообщений служит действие, которое называется: ActionMessage, или MessageAction, или просто Message.

Основной аргумент: произвольные данные этого сообщения - data.
Его можно задать двумя способами. Если эти шесть (или меньше) байт представляют собой строчку печатных символов, то и указать их можно в виде строки, например

Message(data="Hello!");

А если это просто числовые данные, то можно указать значение каждого одельного элемента массива data, например:

Message(data[0]=123, data[0]=0, data[0]=200, data[0]=255, ...);

Другими дополнительными аргументами являются report и значение флага genkeyevent (другое название - generatekeyevent).

Аргумент report определяет - в какой момент посылать событие - при нажатии или отпускании клавиши. Он может иметь значения:

  • pss (или keypss) - сообщение посылается в момент нажатия клавиши
  • release (или keyrelease) - сообщение посылается в момент отпускания клавиши
  • all - посылать сообщение и при нажатии, и при отпускании клавиши. Обратите внимание, что data в обоих сообщениях будут одни и те же. Но в том же сообщении есть поле, которое указывает - что происходило с клавишей при посылке сообщения (нажатие или отпускание).
  • none - сообщение вообще не посылается.

Флаг genkeyevent определяет - должна ли эта клавиша генерировать также обычное сообщение о нажатии/отпускании клавиши. Понятно, что при genkeyevent=yes кроме message посылается и обычное клавиатурное событие, в противном случае посылается только message. По умолчанию genkeyevent=no.

Эмуляция нажатия другой клавиши.

Это действие позволяет изобразить нажатие клавиши с другим скан-кодом (keycode). Оно может оказаться полезным на "сокращенных" клавиатурах, которые не имеют всех нужных физических клавиш.
В общем-то ту же проблему можно решить с помощью перекрытий (overlay). Так что эти механизмы во многом дублируют друг друга.

Существенное отличие этого механизма (с помощью действий) в том, что кроме собственно keycode можно сразу указать и набор модификаторов, которые будут в сообщении о нажатии/отпускании эмулируемой клавиши взамен текущих.

Итак. Название действия: Redirect или RedirectKey.
Основной аргумент: keycode (другие названия - key или kc).
Его значение - название (не числовое значение!) keycode, такое как описано в фалах типа xkb_keycodes.

Два других аргумента служат для указания набора модификаторов - clearmodifiers (или clearmods) и modifiers (или mods). Как понятно из названий первый из них задает модификаторы, которые нужно "вычистить" из набора текущих, а второй - те, которые добавить в этот набор.

Значение этих аргументов такое же как в действиях меняющих текущий набор модификаторов. То есть - название реальных и/или виртуальных модификаторов. Если модификаторов несколько они разделяются знаком "+".

Выключить X-сервер.

Название действия: Terminate или TerminateServer.
Результат этого действия такой же как от нажатия "магической комбинации" Control+Alt+BackSpace.

Аргументов и флагов нет.
Замечу только, что комбинация Control+Alt+BackSpace отслеживается не в XKB и к его действиям отношения не имеет. Поэтому отменить его действия вы в конфигурации XKB не сможете. Можете только добавить еще одну клавишу или комбинацию с аналогичным эффектом.

Переключение экранов (screen).

Это действие в XFree86 не реализовано. То есть вы его можете привязать к какой-нибудь клавише, но никакого эффекта от его применения не будет.

По замыслу оно должно переключать отдельные экраны X-сервера (если их несколько) или переключаться между сервером и консольными терминалами.

Название: SwitchScreen.
Аргумент: screen. Значение аргумента - цело число.
Это еще один случай, когда аргумент может означать абсолютное значение (в данном случае - номер screen'а) или относительное приращение.
В последнем случае перед числом обязательно должен быть знак "+" или "-".

У этого действия есть один флаг - Same (или SameServer).
Если этот флаг присутствует, то речь идет о переключении экранов X-сервера (the same сервер). А если значение флага no, то это действие должно переключать на другой консольный терминал.

Нажатие кнопок на другом устройстве обслуживаемом XKB.

По идее XKB может эмулировать не только события мыши но других устройств ввода (например - joystick). Для эмуляции нажатия кнопок на таком устройстве существует пара действий, аналогичных PointerButton и LockPointerButton.

Первое называется: DevBtn, или DeviceBtn, или DevButton, или DeviceButton.
Второе: LockDevBtn, или LockDeviceBtn, или LockDevButton, или LockDeviceButton.

Как и у "мышинных" действий аргументы этих action - button и count. Но есть еще один обязательный аргумент: dev (или device) - номер устройства.

Действия "особого назначения".

"Пустышка".

В некоторых случаях в таблице действий могут образоваться пустые ячейки. Например тип клавиши подразумевает у нее два shift level, но реально вам нужно действие только в одной из ячеек таблицы. Для заполнения пустых ячеек служит специальная "заглушка" - NoAction().

"Сырое" действие.

Напомню, что мы говорим о том, как действия описываются в текстовых файлах, которые затем компилируются программой xkbcomp. Сами же действия исполняются X-сервером (XKB модулем сервера).

Возможна такая ситуация, что сервер допускает некотрые другие действия о которых xkbcomp еще не знает. (Замечу, что в XFree86 таковых нет.)
На этот случай в xkbcomp предусмотрена возможность просто задать в числовых кодах внутренную структурку описывающую действие.

Для этого существует специальное действие - Private.

Напомню также, что любое действие внутри сервера описывается структурой, которая содержит поля - код, флаги и несколько полей аргументов.
Все эти поля байтовые. Под аргументы отводится 6 байтов. Естественно аргумент может иметь и больший размер, тогда он просто занимает несколько последовательных байтов.

Поэтому аргументами действия Private являются:

  • type - код (или номер) действия
  • data - байтовый массив содержащий флаги и аргументы действия.

Значение для data задаются как для действия Message.
То есть или в виде строки символов (хотя в данном случае это практически бесполезно)

Private(type=123, data="abcde");

или как присваивание числовых значений элементам массива data

Private(type=123, data[1]=0, data[2]=100, data[3]=12);

Объявление "умолчания".

В тех файлах, где могут появиться описания "действий" - xkb_compat и xkb_symbols, могут также использоваться объявления "умолчания".

Они выглядят как оператор присваивания полю структуры в языке C. То есть, в левой части присваивания стиот конструкция состоящая из двух слов, разделенных точкой.

Эти объявления могут использоваться для задания значений флагов "по умолчанию" для "действий" встречающихся в файле. В этом случае первое слово - название "действия", а второе - название флага. Естественно, справа от знака присваивания может быть только логическое значение - True/False.

Например

setMods.clearLock = True;

означает - во всех дальнейших описаниях SetMods, добавляется флаг clearlock.

latchMods.clearLock = True; latchMods.latchToLock = True;

во всех дальнейших описаниях LatchMods, добавляются флаги clearLock и latchToLock.