Файл, типа xkb_compat.

В этом файле описывается поведение клавиш модификаторов - какие изменения происходят в состоянии клавиатуры (изменения битов-модификаторов и "номера группы") при нажатии этих клавиш.

Напомню, что внутри XKB существует структура (таблица) - Xkb Compability Map, которая состоит из двух частей

Если прикладные программы обращаются к X-серверу не специальными XKB-запросами, а запросами к "традиционному" клавиатурному модулю X-сервера, которые должны поменять "привязку" кодов символов (или реальных модификаторов) к скан-кодам, то модуль XKB, выполнив требуемый перенос, пытается также пренести и "действия", "привязанные" к скан-кодам (и некоторые другие параметры клавиши).
Для выполнения такого "переноса" и используется Xkb Compability Map.

В файле типа xkb_compat могут встречаться объявления

Объявление виртуальных модификаторов.

Как и в файле типа xkb_types, прежде всего должны быть объявлены виртуальные модификаторы, которые могут встречаться в дальнейших описаниях. Реальные модификаторы (если они также используются) описывать не надо, поскольку, они имеют стандартные названия. А вот виртуальные модификаторы могут иметь произвольные названия, поэтому, для правильной интерпретации остальных записей необходимо сообщить программе, которая будет "разбирать" этот файл, что соответствующие слова являются названиями виртуальных модификаторов.

Объявление виртуальных модификаторов имеет вид

'virtual_modifiers' список модификаторов ';'
Например,
virtual_modifiers NumLock, AltGr ;

Описание "интерпретации".

Каждая "интерпретация" (interpretation) устанавливает соответствие между кодом какго-нибудь "управляющего" символа (symbol) и "действием" (action), которое должен будет выполнить модуль XKB при нажатии клавиши к которой "привязан" этот символ.

Полностью внутренняя структура, описывающая интерпретацию, состоит из

Естественно, не все эти поля обязательно должны быть заполнены.

Итак, поле "код символа", естественно, определяет символ, к которому "привязывается" "действие", а поле "действие" - само это "действие".

Также, в "интерпретации" могут быть заданы поля "реальные модификаторы" и "критерий соответствия".

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

Если эти поля НЕ заданы, то XKB, при изменнии "привязки" символа к скан-коду, просто перенесет туда же соответствующее "действие".

А вот если эти поля заданы, то прежде чем выполнить перенос, XKB сравнивает набор реальных модификаторов, привязанных к скан-коду и набор реальных модификаторов, указанный в "интерпретации". "Критерий соответствия" определяет - как сравнивать эти два набора (см. ниже).
Если условие выполняется, "действие" переносится.

Кстати, если используются эти два поля (набор модификаторов и "критерий соответствия"), то кода символа может в интерпретации и не быть.

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

Итак. Поле "реальные модификаторы" представляет собой просто один или несколько битов модификаторов.
А "критерий соответствия" представляет собой одно из условий

Кроме того, вместе с любым из перечисленных "критериев" может быть указан "критерий"

Естественно, "по умолчанию" поле модификаторов пустое, а "критерий" - "любой из.. или ни одного".

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

Флаги добавляются в поле "поведение клавиши", а модификатор в поле "виртуальные модификаторы" (эти поля есть у каждого описания скан-кода).

"По умолчанию" поле "флаги" содержит флаг "автоповтор", а поле "виртуальный модификатор" - пустое. Итак. Описание "интерпретации" имеет вид

'interpret' символ '{' описание  '};'
или
'interpret' символ '+' модификатор '{' описание  '};'
или
'interpret' символ '+' критерий '(' модификаторы ') {' описание  '};'
Например
interpret  Nun_Lock {...};
interpret  ISO_Level2 + Shift {...};
interpret  ISO_Lock + AnyOf(Lock+shift) {...};

Если в заголовке указан только код символа, критерий - AnyOfOrNone, поле модификаторов - пустое.

Если указан, код символа и название модификатора (не указан "критерий"), то "критерий" - Exactly.

Если указан "критерий", то в скобках вместо списка модификаторов может стоять слово all. Понятно, что это означает - все модификаторы.

Кроме того, вместо "критерия" и списка модификаторов может использоваться слово Any. Это означает - AnyOf(all).

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

interpret Any + Any {...};
означает, что эта "интерпретация" применяется ко всем клавишам, у которых есть реальные модификаторы.

Внутри описания "интерпретации" могут быть строчки типа оператора присваивания

useModMapMods

Служит для указания "критерия" LevelOneOnly. Если справа стоит слово "level1" или "levelone", то "критерий" проверяется. Если слова "anylevel" или "any" - игнорируется. Кстати, "по умолчанию" он игнорируется, так что строчки вида

useModMapMods = anylevel;
особого смысла не имеют.

repeat и locking

Устанавливают значения для флагов "автоповтор" и "залипание". Справа от присваивания должно быть логическое значение - True или False.
Например,

repeat = True;
locking = False;

virtualModifier

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

Справа от присваивания просто указывается название виртуального модификатора.
Например,

virtualModifier = AltGr;

action

Описывает "действие". Подробнее об этом читайте "Описание действий".
Здесь замечу, что "действие" также может быть "пустым". Если "интерпретация" нужна для того, чтобы перенести не "действие", а только "флаги" или "виртуальный модификатор", то ее описание может выглядеть как

interpret ... {
  repeat = False;
  locking = True;
  action = NoAction();
};

Объявление "отображения номера группы в модификатор".

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

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

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

Это объявление имеет очень простой вид.

'group' номер группы '=' модификатор ';'
Например,
group 2 = AltGr;

Описание поведения индикатора.

В файлах типа xkb_compat также описывается "поведение индикаторов", хотя к "таблице совместимости" (compability) они отношения не имеют.

Напомню, что в XKB можно определить до 32 индикаторов. Первые 3-4 (в зависимости от типа клавиатуры) отображаются реальными "лампочками" на клавиатуре, а остальные считаются "виртуальными" и могут отображаться специальными программами.

В файле типа xkb_keycodes индикаторам даются символические имена (связыватся номера индикаторов и "имя индикатора").

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

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

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

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

Итак. Описание поведения индикатора имеет вид

'indicator' имя_индикатора '{' описание  '};'

Здесь "имя_индикатора" - это то символическое имя (строка символов в двойных кавычках), которое было дано ему в файле xkb_keycodes.

А "описание" обычно имеет вид оператора присваивания (исключение - логические переменные-флаги, которые могут принимать значения только True/False).

В этих "описаниях" могут встретиться строчки типа

modifiers, groups и controls

Определяют - какие компоненты "состояния" должен отслеживать индикатор.
Естественно, справа от знака присваивания должен быть ...

Надо отметить, что номер группы можно задавать

whichModState и whichGroupState

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

Справа от присваивания может быть слово

По умолчанию (то есть, если which...State явно не указаны) подразумевается effective.

allowExplicit

Логический флаг, который разрешает (запрещает) прикладным программам включать/выключать индикатор. Обратите внимание, конечно, для включения/выключения индикатора прикладная программа посылает специальные запросы к XKB. Но XKB по этим командам только меняет (если это разрешено) только состояние индикатора, не затрагивая свое "состояние". Естественно, при этом состояние индикатор может не соответствовать состоянию XKB.

Поскольку allowExplicit является логической переменной, справа от присваивания должно быть только True или False.

Можно также использовать другую форму этой инструкции. Так, просто указание

allowExplicit;
эквивалентно
allowExplicit = True;
а строчка
!allowExplicit;
эквивалентна
allowExplicit = False;
По умолчанию этот "флажок" - True. То есть, прикладным программам разрешено менять состяние индикатора, помимо "состояния клавиатуры".

drivesKeyboard

Имеет много синонимов - drivesKbd, ledDrivesKbd, ledDrivesKkeyboard, indicatorDrivesKbd, indicatorDrivesKeyboard.

Это тоже логический флаг, который заставляет XKB устанавливать "обратную связь" между индикатором и "состянием клавиатуры". То есть, если это флаг "взведен" (и разрешено allowExplicit), то, при изменении прикладной программой состяния индикатора, XKB должен изменить и связанные с ним компоненты "состяния клавиатуры".

Обратите внимание, что

При этом, если "which...state" - none, base или any, никакого эффекта не будет. А effective эквивалентно locked. Напомню, что по умолчанию подразумевается значение effective, следовательно - если инструкций вида "which...state" в описании нет, то изменения будут делаться в locked Group или locked Modifiers, соответственно.

Как и в случае с флагом allowExplicit, объявление drivesKeyboard должно иметь вид

drivesKeyboard = True; ( эквивалент - drivesKeyboard;)
или
drivesKeyboard = False; ( эквивалент - !drivesKeyboard;)

index

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

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

Это объявление является воспомогательным и позволяет определить какое-нибудь поле (инструкцию) для всех записей типа interpret или indicator. Естественно, обычно эти объявления помещаются в начале файла (или блока в файле).

Они меют вид оператора присваивания, где в левой части указывается конструкция типа "поля структуры" в языке C.
Например,

indicator.allowExplicit = False;
что означает - во всех дальнейших описаниях индикаторов (indicator) подразумевается "allowExplicit = False;", если конечно, эта инструкция не указана явно.

Первым словом в левой части (то, что до точки) должно быть


Иван Паскаль pascal@tsu.ru