Основное назначение модуля XKB — преобразовывать скан-коды нажимаемых клавиш в коды символов.
Обычно в документации XKB скан-коды называются keycodes, а коды символов - просто "символы" (symbols).
Естественно, "символы" - это не обязательно коды "печатных" символов (букв, цифр, знаков препинания и т. п.). Это могут быть также "управляющие" коды (Esc, Enter, Backspace и т. п.) или коды, которые никак не отображаются, но влияют на внутренне состояние самого XKB (переключение РУС/ЛАТ, Control, Shift, Alt и т.п.) и, следовательно, на то, какой символ будет выбран при нажатии обычных "буквенных" клавиш.
Прежде всего следует сказать несколько слов о том, как происходит преобразование скан-кодов в символы при работе X Window System без модуля XKB.
Сам X-сервер переводом скан-кода в код символа не занимается. При нажатии или отпускании кнопки клавиатурный модуль X-сервера посылает сообщение о событии (event) прикладной программе.
В этом сообщении указывается только скан-код нажатой кнопки и "состояние клавиатуры" - набор битовых флагов, который отражает состояние клавиш-модификаторов (Shift, Control, Alt, CapsLock и т. п.).
Клиентская программа должна сама решить, какой символ соответствует скан-коду при таком сочетании битов-модификаторов.
Естественно, для этого программа может воспользоваться таблицей, хранящейся в X-сервере, в которой для каждого скан-кода перечислены возможные символы. Обычно програма при старте запрашивает эту таблицу у сервера. (Таблицу на сервере можно менять с помощью утилиты xmodmap).
Разумеется, при создании программ никто не пишет каждый раз процедуру
для интерпретации скан-кодов. Для этих целей существуют специальные
подпрограммы в библиотеке Xlib.
Конечно, Xlib используется не только для этого. Это библиотека
низкоуровневых процедур для работы с X-сервером. Даже если
программа пользуется высокоуровневыми библиотеками-"тулкитами" (Xaw,
Motif, Qt, gtk и т. п.), библиотека Xlib служит "базовой" для этих
тулкитов.
Итак, процедуры из Xlib, зная скан-код и состояние клавиатуры, в соответствии с таблицей символов, полученной от сервера при старте, выбирают подходящий символ.
Модуль XKB точно так же сообщает программе только скан-код и свое "состояние". В отличие от "старого" модуля (обычно говорят - "core protocol", будем его называть для краткости - "core-модуль"), XKB имеет более сложную таблицу символов, другой набор модификаторов и некоторые дополнительные параметры "состояния клавиатуры" (обо всех этих отличиях мы поговорим по ходу рассмотрения "внутренностей" XKB).
Для полноценной работы с XKB библиотека Xlib должна содержать
процедуры преобразования скан-кодов, "знакомые с Xkb".
Естественно, "иксы", у которых X-сервер "укомплектован" модулем XKB,
имеют и соответствующую библиотеку Xlib.
Таким образом, XKB фактически делится на две части - модуль, встроенный в X-сервер, и набор подпрограмм, входящих в библиотеку Xlib.
Однако же, никто не запрещает использовать программы, которые были собраны
со старой библиотекой Xlib, "не подозревающей" о существовании XKB:
при этом и возникает "проблема совместимости". Модуль XKB
должен уметь общаться как со "своей" Xlib, так и со старой, работающей в
соответствии с core protocol.
Естественно, "общение" не ограничивается только передачей сообщений о
нажатии/отпускании клавиш. Процедуры Xlib могут обращаться к X-серверу
с различными запросами (например, взять таблицу символов) и командами
(например, поменять в этой таблице расположение символов).
На все эти запросы и команды модуль XKB должен реагировать так, чтобы
даже "старая" Xlib могла работать правильно (насколько это возможно).
Что же собой представляет таблица символов, связывающая символы со скан-кодами и состоянием модификаторов? Рассмотрим сначала "традиционную" таблицу символов, которая используется в core protocol.
Как и во многих других клавиатурных модулях, ее можно представить как обычную двумерную таблицу, где каждая строка соответствует скан-коду, а столбцы - модификаторам или комбинации модификаторов.
Прежде всего надо заметить, что в "сообщении о нажатии/отпускании клавиши"
под биты-модификаторы отводится один байт (октет) и соответственно, существует
восемь битов-модификаторов. Первые три называются - Shift, Lock, Control,
остальные "безымянные" - Mod1, Mod2, Mod3, Mod4, Mod5.
Замечу, что хотя названия первых трех модификаторов явно намекают на то,
каким клавишам они должны соответствовать, на самом деле они могут быть
"привязаны" (то есть, менять свое значение при нажатии/отпускании клавиши)
к любым другим кнопкам.
В данном случае нам важно, что восемь модификаторов могут составить 256
различных комбинаций. Поэтому теоретически таблица символов может содержать
до 256 столбцов. В то же время, в core protocol'е строго определены только
первые четыре колонки, в смысле - каким комбинациям модификаторов они
соответствуют. Легко догадаться, что в этих комбинациях используются только
два модификатора - Shift и Mode_switch.
(Вы можете заметить, что среди модификаторов нет бита с именем
Mode_switch. Совершенно верно. Его роль выполняет один из "безымянных",
модификаторов - Mod1-Mod5. А Mode_switch - это название
одного из служебных символов. Когда приложение запрашивает у сервера
таблицу символов, оно также выясняет, какой из безымянных модификаторов
связан с этим символом, и в дальнейшем по состоянию этого модификатора
догадывается о том, нажал ли пользователь клавишу, соответствующую
символу Mode_switch.)
Итак. Первые четыре колонки в таблице соответствуют "состояниям" -
"никаких модификаторов" | Shift | Mode_switch | Mode_switch+Shift |
---|
В терминах core protocol можно сказать, что состояние
Mode_switch выбирает одну из двух
групп (не надо путать их с XKB группами, о которых мы поговорим
позднее), а состояние Shift - одну из двух колонок внутри группы.
Как вы скорее всего знаете, разные группы обычно используются для
разных языков (алфавитов), а Shift выбирает строчные или
прописные буквы
в пределах одного алфавита.
Group 1 | Group 2 | |||
---|---|---|---|---|
Shift | Mode_switch | Mode_switch+Shift | ||
... | ||||
keycode 38 | a | A | Cyrillic_ef | Cyrillic_EF |
keycode 39 | s | S | Cyrillic_yeru | Cyrillic_YERU |
keycode 40 | d | D | Cyrillic_ve | Cyrillic_VE |
... |
Заметьте также, что ни Lock, ни Control в выборе символа из таблицы не участвуют. Если эти модификаторы активны, то отдельные подпрограммки Xlib после выбора символа из таблицы делают соответствующие преобразования этих символов.
Вернемся к XKB. Как видите, недостаток "традиционной" таблицы - ее "негибкость". Хотя колонок может быть до 256, "стандартно" обрабатываются только первые четыре, причем их зависимость от состояния модификаторов жестко "зашита" в алгоритмах Xlib.
Поэтому одно из основных усовершенствований, которые были внесены при разработке XKB - большая гибкость в построении таблицы.
Делить таблицу на группы удобнее. Во-первых, так легче провести границу
между разными алфавитами (если, конечно, таковые используются в раскладке).
Заметьте, что в некоторых случаях хотелось бы иметь не два разных алфавита,
а больше. Причем раскладки для разных алфавитов могли бы составлять
разные люди, независимо друг от друга
Во-вторых, чем больше модификаторов участвуют в выборе колонок,
тем сложнее и запутаннее становятся соответствующие описания зависимостей.
Поэтому, авторы XKB использовали радикальный подход - в одной и той же раскладке может быть несколько (до четырех) отдельных таблиц. Вот эти таблицы и называются группами XKB (или просто groups).
Вообще-то, правильнее сказать не "несколько двумерных таблиц в одной
раскладке", а - у каждого скан-кода (keycode) может быть до четырех
"однострочных" таблиц - групп.
Потому, что ...
Итак.
keycode | номер группы | количество level'ов | ||||
---|---|---|---|---|---|---|
36 | 1 | одна колонка | Enter | |||
38 | 1 | две колонки | a | A | ||
2 | две колонки | Cyrillic_ef | Cyrillic_EF | |||
3 | две колонки | Greek_alpha | Greek_ALPHA | |||
21 | 1 | две колонки | + | = | ||
2 | четыре колонки | + | = | \ | ; | |
... |
Наконец, надо сказать, что групп может быть от одной до четырех, а уровней - до 64.
Кроме "таблицы символов" к скан-коду может быть "привязана" аналогичная "таблица действий" (actions). Эта таблица также делится на подтаблицы (группы) и колонки (уровни).
В отличие от таблицы символов, которая используется приложением (X-сервер ее только хранит, чтобы сообщить каждому вновь стартующему приложению), таблица действий используется самим сервером.
В ее ячейках располагаются вызовы внутренних процедур XKB, которые меняют его состояние - текущую группу, состояние модификаторов и внутренних флагов XKB.
Точнее - действия, выполняемые actions, не ограничиваются измениями состояния XKB. Они также используются для
Немного подробнее о всех возможных actions написано в разделе Описание действий.
Если на клавише для группы и позиции в группе определено действие, то для этой же группы и позиции в группе для той же клавиши должен быть определен символ (обычно служебный).
Заметим, что в core-модуле понятия "действие" вообще нет.
Текуший номер группы хранится в "таблице состояния" XKB.
Точнее, внутри XKB имеются три ячейки
Наконец, существует понятие "фактической" (effective) или "действующей" группы. Именно ее значение используется для выбора подтаблицы-группы в таблице символов и таблице действий. Это значение не хранится, а каждый раз вычисляется в виде суммы трех вышеуказанных переменных.
Естественно, при таком суммировании может получиться число, большее чем количество заданных групп. Чтобы получить из него какой-нибудь допустимый номер группы, XKB может использовать три разных метода:
Кроме переменных, содержащих номера групп, "состояние XKB" определяется "флажками" - модификаторами. Эти битовые флаги меняются при нажатии клавиш Shift, CapsLock, Alt, Control и т. п. и, естественно, влияют на выбор подходящего символа из таблиц.
Как я уже упоминал, "core protocol" (протокол "общения" между "традиционным"
клавиатурным модулем и Xlib)
тоже имеет "набор модификаторов" (который и сообщается прикладной программе
при нажатии кнопок). Эти модификаторы (8 бит) называются Shift, Lock, Control,
Mod1-Mod5. В зависимости от их состояния Xlib выбирает подходящий символ
и может выполнять дополнительные действия — делать из обычных символов
управляющие, менять прописные/строчные буквы и т. п.
Кроме того, программа может сама (помимо Xlib) по-своему
интерпретировать эти модификаторы и менять свое поведение.
Поэтому, хотя XKB имеет больше модификаторов и его поведение (действия, выполняемые при определенной комбинации модификаторов) можно гибко перестраивать (как при старте, так и в процессе работы), модуль XKB вынужден эмулировать "классический" набор модификаторов, специально для старых клиентских программ (и старой Xlib).
Итак. Модификаторы core protocol'а в XKB называются "реальными" (real) модификаторами и их названия такие же, как в core protocol.
Кроме того, XKB имеет еще 16 своих внутренних модификаторов, которые называются "виртуальными" (virtual) модификаторами.
К сожалению, "проблема совместимости" заключается еще и в том, что в формате "сообщения о клавише" для модификаторов отведено только восемь бит. Поэтому XKB при всем желании не может сообщить приложению все свои шестнадцать виртуальных модификаторов и вынужден в любом случае отображать их в "реальные" (даже для приложений "знакомых с XKB"). Единственным утешением является то, что можно сколько угодно виртуальных модификаторов отобразить в один реальный и это отображение легко перенастраивается.
Итак. Эти модификаторы выполняют несколько функций
Так же как и номер группы, набор битов-модификаторов внутри XKB существует в трех экземплярах (в трех переменных)
Как и для номеров групп, для модификаторов существует "фактический" набор модификаторов, который определяется как логическая сумма (побитная операция ИЛИ) трех указанных переменных. Соответственно, никаких дополнительных "выравниваний", как для значения номера группы, не требуется.
В отличие от номера группы, уровень не запоминается в состоянии XKB, а вычисляется из состояния модификаторов. При этом для различных клавиш зависимость уровня от модификаторов может различаться.
Для того чтобы обеспечить такую гибкость, в XKB существут понятие "тип клавиши".
В каждом описании типа клавиши задается некая функция - какие модификаторы
принимать к рассмотрению и какой уровень должен получится при определенном
сочетании модификаторов.
Соответственно, у каждой клавиши (скан-кода) в каждой под-таблице
(группе) указывается свой "идентификатор типа".
Естественно, при нажатии клавиши XKB (точнее, процедуры Xlib) определяет, к какому типу она относится и по описанию типа и текущему состоянию модификаторов вычисляет, из какого уровня следует выбрать символ для этого скан-кода.
Надо отметить, что хотя описания типов и принадлежность каждой клавиши к определенному типу можно гибко менять, в XKB по умолчанию задан основной набор типов и для всех клавиш расписаны идентификаторы типов. Поэтому обычно нет необходимости задавать эти параметры в файлах конфигурации XKB.
Кроме таблицы символов (и, возможно, "действий") с каждым скан-кодом связаны еще несколько переменных
Поскольку разные клавиши могут иметь разное количество групп, может возникнуть ситуация, когда вычисленный и "выровненный" эффективный номер группы все-таки не попадает в дапазон допустимых групп для данной клавиши.
В этом случае эффективный номер группы может дополнительно "выравниваться", специально для данной клавиши.
Возможные методы точно такие же, как и "глобальные". По умолчанию используется метод Wrap.
Эта переменная состоит из двух частей - набора флагов и дополнительного аргумента. Обычно аргумент не нужен. Но некоторые флаги подразумевают дполнительный числовой аргумент, а смысл этого аргумента зависит от флага.
Флаги определяют
Это битовая маска, которая указывает - какая информация, связанная с клавишей, "задана точно" (explicit) и не должна изменяться в некоторых случаях. Дело в том, что в core protocol определены команды, с помощью которых программы могут менять "раскладку клавиатуры" внутри клавиатурного модуля X-сервера. Естественно, эти комады меняют только "привязку" символов, поскольку другие "свойства" скан-кодов в core protocol'е не определены.
Для того, чтобы XKB мог при этом поменять и "привязку" других "свойств", в нем предусмотрен специальный механизм - "интерпретации" символов (об этом см.ниже).
Так вот. Набор "исключений" может защитить информацию, связанную с
конкретным скан-кодом, именно от таких косвенных изменений.
Если прикладная программа будет пользоваться соответствующим запросами
XKB модуля (а не core protocol), такой защиты не требуется.
Итак, с помощью этой маски можно запретить
Обратите внимание, что с каждым скан-кодом связаны две разные переменные (modmap и vmodmap), одна для реальных модификаторов, другая - для виртуальных.
Набор реальных модификаторов служит для эмуляции "традиционного" набора модификаторов (в соответствии с core protocol), а набор виртуальных модификаторов может служить аргументами для "действий", связанных с этой клавишей.
Надо заметить, что изменения набора виртуальных модификаторов (base, locked и latched) делается с помощью соответствующих "действий". Естественно, одним из аргуметов этого "действия" должен быть модификатор (или несколько модификаторов), которые нужно установить/сбросить в соответствующих "переменных состояния". Так вот, при описании "действия", модификаторы можно указать явно, а можно просто сослаться на vmodmap (то есть - "установить витруальные модификаторы, привязанные к этой клавише").
А вот изменение модификатора в "эмулируемом наборе модификаторов" происходит автоматически при нажатии/отпускании клавиши. Естественно, устанавливаются/сбрасываются именно те модификаторы, которые указаны в наборе реальных модификаторов (modmap).
Кроме того, эти два набора служат для установления соответствия между реальными и виртуальными модификаторами. Надо заметить, что виртуальный модификатор не имеет никакого смысла, если не связан с каким-нибудь реальным модификатором.
Кроме номера группы и набора модификаторов, в XKB существует аналогичный набор для "управляющих флагов". Правда, в отличии от номера группы и набора модификаторов, которые "размазаны" по трем переменным (base, locked, latched), набор управляющих флагов только один.
В "управляющие флаги" входят все те "флажки", которые не попали в
"набор модификаторов". Они не сообщаются приложению, а используются
XKB для переключения его внутренних режимов.
Эти флаги управляют
"Управляющие флаги" (как и номера групп и модификаторы) меняются соответствущими действиями, привязанными к подходящим клавишам.
Как известно, на клавиатуре кроме "кнопок" имеется несколько "лампочек"-
индикаторов. Управление этими индикаторами тоже входит в обязанности XKB.
В XKB может существовать до 32 индикаторов.
Естественно, на клавиатуре отображаются только первые 3-4 из них.
Эти индикаторы называются в XKB "физическими", а остальные - "виртуальными".
Состояние виртуальных модификаторов может быть считано из XKB и отображаться
на экране специальными программами (xkbvleds, mxkbledpanel).
Каждый индикатор может быть связан с компонентом "состояниея XKB" (модификатором, номером группы, "управляющим флагом") и, соответственно, состояние индикатора будет автоматически отражать состояние своего "компонента состояния XKB".
Причем, в XKB существуют специальные запросы, которыми прикладная программа может управлять состянием какого-нибудь индикатора ("зажигать"/"гасить" его). Заметьте, речь идет о том, что программа может просто включать/выключать "лампочку", а не менять состояние клавиатуры, которое "отслеживается" этой "лампочкой".
Поэтому, с каждым индикатором связан набор флагов, который определяет
Как уже упоминалось, XKB вынужден решать "проблему совместимости" с программами, которые не подозревают о существовании XKB и обращаются с запросами к "core-модулю" X-сервера.
Естественно, модуль XKB может обработать эти запросы, но основная проблема, возникающая при этом, состоит в том, что в модуле XKB вводятся некоторые новые понятия (новые относительно core protocol'а), которые никак не отражены в "традиционных" запросах к клавиатурному модулю.
Более того. XKB вынужден поддерживать "традиционный" формат "сообщения о
нажатии/отпускании" клавиши, в котором передается "состояние" клавиатурного
модуля, состоящее из набора реальных модификаторов. Даже если модуль XKB
общается с XKB-совместимой Xlib, он вынужден, для передачи ей информации
о состоянии своих виртуальных модификаторов, "превращать" их в реальные.
(Поэтому, кстати, виртуальный модификатор не оказывает никакого эффекта,
если он не "отображен" в какой-нибудь реальный).
Таким образом, в "традиционном" протоколе номер группы отображается одним из модификаторов - "основная группа/альтернативная группа", а в модуле XKB, в "состоянии клавиатуры" явно существует двухбитное поле - "номер группы" (которое, к тому же, не "перекрывается" с набором модификаторов).
Кроме того, в "традиционном" модуле клавиатуры каждая группа состоит ровно из двух "уровней". Хотя при этом допускается, что каждому скан-коду может быть сопоставлен одномерный массив символов длиной до 256. Первые четыре ячейки в нем соответствуют "двум группам, в каждой по два уровня". Остальные ячейки "клиентская" программа может выбирать сама, в зависимости от состояния модификаторов Mod1-Mod5.
Поэтому, для совместимости модуль XKB, при общении со "старыми" программами, вынужден ...
Для решения этой проблемы в XKB хранится таблица "интерпретаций" (interpretation) управляющих символов. Эта таблица связывает коды символов и вызовы соответствующих "действий" (actions). Естественно, в этой таблице присутствуют только специальные "управляющие" символы ( Caps_Lock, Shift, Num_Lock, "переключатель РУС/ЛАТ" и т.п.).
Кроме самих символов и "действий" в таблице интерпретаций хранится также дополнительная информация - список "реальных модификаторов" и "критерий соответствия" ("любой из модификаторов", "все указанные модификаторы", "только указанные модификаторы" и т.п.).
Каждый раз при изменении "привязки" символа (учтите, что это изменение может происходить при старте X-сервера, как часть "начальной настройки" сервера) модуль XKB проверяет - присутствует ли в этот символ в "таблице интерпретаций". И если символ там есть, то XKB, "присвоив" этот символ требуему скан-коду, добавляет этому скан-коду и соответствующее "действие". Дополнительная информация (модификаторы и "критерий соответствия") тоже может использоваться при "поиске" подходящего места для "действия".
Кроме того, применение "интерпретации" может поменять некоторую другую информацию, связанную со скан-кодом - флаги, отвечающие за "автоповтор" и "залипание" клавиши и "список виртуальных модификаторов".
Напомню, что у каждого скан-кода может быть указан набор "исключений", который защитит информацию, связанную со скан-кодом от применения "интерпретации".
Надо отметить, что помещать все "действия" в "таблицу интерпретаций", а не присваивать их непосредственно скан-кодам - является "хорошим тоном". Поскольку в "таблице интерпретаций" "действие" связывается с символом, а не со скан-кодом, и, к тому же, "перенос" "действий" из "таблицы интерпретаций" в соответствуюшие таблицы "действий" скан-кодов XKB выполняет каждый раз при загрузке конфигурации (в том числе и при старте X-сервера), модуль XKB сам найдет подходящее место для соответствующего "действия" и, таким образом, корректно "свяжет" символы и действия (в таблицах, назначенных скан-кодам).
Модуль XKB позволяет объединять несколько клавиш в "радио-группу". То есть, клавиши одной ради-огруппы являются взаимозависимыми. При нажатии одно из клавиш группы все остальные из этой группы "отжимаются".
Естественно, нажатая клавиша остается "залипшей", пока не будет нажата другая клавиша из этой группы. Принадлежность конкретной клавиши к некоторой радио-группе задается в поле "поведение клавиши".
Там же можно определить дополнительное свойство - можно ли "отжать" все клавиши радио-группы. Обычное определение радио-группы подразумевает, что одна из клавиш группы должна быть нажата, а чтобы отжать ее, надо нажать другую клавишу в группе (естественно, теперь она будет "залипшей"). Если задано свойство "могут быть отжаты все", то "залипшую" клавишу группы можно "отжать" просто повторным нажатием (при этом никакая другая клавиша группы не окажется "залипшей").
В XKB можно объявить до 127 радио-групп (хотя это может зависить от конкретной реализации XKB).
В модуле XKB можно для некоторых клавиш (группы клавиш) задать набор "альтернативных" скан-кодов. То есть, при нажатии такой клавиши клавиатура выдает некоторый скан-код, который и должен быть интерпретирован XKB (выбрать подходящий символ), но, если включен режим замены скан-кода на "альтернативный", то XKB прежде всего заменяет этот скан-код соответствующим "альтернативным", а потом уже новый скан-код пытается интерпретировать.
Такая группа называется "перекрытием" (overlay). Их может быть всего две. Принадлежность конкретной клавиши к конкретной группе-"перекрытию" и "альтернативный" скан-код задаются в поле "поведение клавиши".
Это свойство используется для клавиатур, у которых очень маленький набор клавиш (например в "лаптопах"). Например, на такой клавиатуре может полностью отсутствовать "дополнительная цифровая клавиатура" (keypad). Поскольку некоторые приложения могут потребовать, чтобы какие-то действия в них вызывались нажатием кнопок именно на keypad, модуль XKB может эмулировать эту дополнительную клавиатуру, используя, например, "цифровые" кнопки на основной клавиатуре.
Имеются ввиду люди у которых подвижность рук (пальцев) ограничена или они вынуждены пользоваться какими-либо маханическими приспособлениями для работы с клавиатурой.
Проблемы, которые могут возникнуть при этом:
Все эти режимы осуществляются частью XKB модуля, которая называется AccessX. Все режимы можно включать и выключать по отдельности изменяя состяние одноименных "управляющих флагов XKB" (XKB Controls).
Обратите внимание, что само включение режимов AccessX может быть проблемой. (Представьте себе, что человеку нужен режим StickyKeys, а для его активизации нужно нажать сложную комбинация из нескольких клавиш). Поэтому для включения некоторых режимов используются специальные действия:
С другой стороны, если один из режимов AccessX включен, а компьютер
используется разными пользователями, то человку не имеющему ограничений
он может наоборот мешать. Поэтому в XKB предусмотрено автоматическое
отключение режимов AccessX, если в течении некоторого времени клавиатура
никак не использовалась. Кроме того, режим StickyKeys (эмуляция одновременного
нажатия через последовательное) автоматически выключиться, если вы нажмете
несколько клавиш действительно одновременно.
Саму возможность автоматического выключения AccessX по таймауту можно
(как и другие режимы) включить/выключить соответствующим флагом
(AccessXTimeout) в XKB Controls.
И наконец - в AccessX предусмотрен дополнительный режим звуковой индикации
всех происходящих событий - начало и окончание всевозможных таймаутов, а также
включение и выключение LED'ов. Для того, чтобы лучше ориентироваться в
этх событиях (особенно если включено несколько разных режимов AccessX) XKB
старается озвучивать их звуками разной длительности и тона (насколько позволяет
"железо").
Этот режим, как и другие может быть включен/выключен соответсвующим
флагом (AccessXFeedback) в XKB Controls. Кроме того, можно по отдельности
включить/выключить озвучивание отдельных событий.
XKB может эмулировать события мыши с помощью клавиатуры. То есть, его можно настроить так, что при нажатии определенных клавиш X-сервер будет посылать приложению сообщения (events) не о нажатии/отжатии кнопок, а о перемещении мыши и нажатии кнопок на мышке.
Делается это с помощью соответсвующих действий (actions) - перемещение мыши, нажатие кнопки мыши, выбор кнопки "по умолчанию".
Рассмотрим их немного подробнее.
Кроме того, существует два режима (mode) перемещения мыши - простой и "с ускорением" (accelerated). При одиночном нажатии клавиши разница между ними незаметна. А вот если вы держите клавишу нажатой и работает автоповтор, тот в обычном режиме на каждый автоповтор указатель смещается на одно и то же количество точек (заданое в аргументах действия). А в accelerated mode указатель начинает ускоряться, то есть с каждым новым автоповтором размер одиночного шага растет.
Весь процесс ускорения описывается несколькими дополнительными параметрами, которые хранятся во внутренних переменных XKB (являются частью "состояния" XKB). (Надо заметить, что режим ускорения имеет свои параметры автоповтора - задержку между реальным нажатием клавиши и первым повтором и интервал между повторорами.) Итак, эти параметры (числовые) описывают
Включение и выключение эмуляции мыши и выбор режима движения выбирается двумя управляющими флагами XKB (XKB Controls) - MouseKeys и MouseKeysAccel.
Надо заметить, что по умолчанию все нужные действия описаны и привязаны к кнопкам "дополнительной цифровой клавиатуры" (NUMPAD). Для включения и выключения режима эмуляции мыши используется комбинация Shift+NumLock.
Вообще-то, эта часть XKB имеет малое отношение к клавиатуре.
Более того, для пользователей компьютеров, в которых клавиатура, дисплей
и "спикер" - независимые устройства, такое совмещение может показаться очень
странным. Но поскольку, в некоторых архитектурах динамик "пищалки" находится
в клавиатуре и издает звук (key_click) при каждом нажатии клавиши,
в "иксах" считается, что управление "пищалкой" - дело клавиатурного модуля.
Надо отметить, что управление "пищалкой" заложено еще в традиционном (core) модуле клавиатуры. С помощью стандартных запросов к X-серверу, приложение может регулировать параметры key_click'а (высоту тона, длительность и громкость), а также вызвать этот click при необходимости.
В XKB разработчики пошли еще дальше и предусмотрели возможность вместо простого "писка" проигрывать "музыкальные фрагменты". Естественно, обеспечить такое "музыкальное сопровождение" для клавиатурного модуля слишком сложная задача. Во-первых нужна "база данных" различных звуков (хотя бы просто в виде набора аудио-файлов), а во-вторых музыка может воспроизводится различными "железками" (звуковыми картами), каждая из которых требует "особого подхода" (драйвера).
Поэтому, по замыслу разработчиков, выбором конкретного звука и его воспроизведением должна заниматься отдельная программа (назовем ее - "музыкальная приставка"). А модуль XKB вместо "писка" просто генерирует специальное сообщение (event), которое так же как и обычные event'ы X-сервера могут быть доставлены любой программе. "Музыкальная приставка" только должна при старте сообщить X-серверу, что ее интересует определенная разновидность event'ов (в данном случае - bell-event'ы от модуля XKB).
Естественно, если такая "музыкальная приставка" существует, ее возможности
не ограничиваются воспроизведением "писков" разной частоты и длительности.
Она может проигрывать множество разных музыкальных фрагментов из своей
"базы данных".
Поэтому, в сообщениях XKB указывается не "параметры писка", а просто
некое "имя звука" (bell name). Естественно, "музыкальная приставка"
должна иметь какой-то конфигурационный файл, в котором для каждого
"имени звука" назначен свой музыкальный фрагмент.
Соответственно, теперь любое приложение с помощью соответствующих запросов к X-серверу (теперь уже не в core-формате, а в формате XKB), может заказать не просто "писк" с определенным тоном и длительностью, а любой звук, указав его имя (bell name).
При этом XKB собственно является просто "ретранслятором". Он даже не анализирует правильность "имени звука", а просто, получив запрос от любого приложения, передает его в виде своего event'а "музыкальной приставке".
Естественно, в такой схеме XKB кажется даже лишним. Приложение могло бы и само общаться с "музыкальной приставкой". Но не забудьте, что сама идеология "иксов" допускает, что приложение, X-сервер и "музыкальная приставка" могут быть запущены на различных машинах. Поэтому, нормальное приложение должно было бы, кроме соединения с X-сервером, найти еще и "музыкальную приставку" и установить с ней контакт.
В схеме с XKB, любое приложение отправляет свои запросы тому же самому X-серверу (с которым ему и так приходится общаться), а уж администратор сервера определяет - кто и как будет обслуживать эти запросы. Кроме того, при этом вводится некоторый стандарт на общение между приложением и "звуковой приставкой" (разве что, кроме самих "имен звуков").
Надо заметить также, что XKB не только ретранслирует запросы, но и сам может "заказать звук" при некоторых изменениях своего внутреннего состояния (состояния индикаторов, флагов и т.п.).
Иван Паскаль [email protected]