Добавляем новую "старую" раскладку клавиатуры.

Рассмотрим - как добавить еще одну группу с другой расскладкой клавиатуры.

Зачем это может понадобится?

Ну, например, проблема (описанная в "Почему руссификация не работает?") - у вас есть программы, в "бинарниках", статически слинкованные, которые напрочь отказываются понимать коды типа Cyrillic_*. Можно специально для них изготовить раскладку, в которой будут не двубайтные коды русских букв, а однобайтные коды KOI8-R.

Возможно, вам захочется добавить раскладку в кодировке cp1251 или еще какой-нибудь, которая отличается от стандартной расположением русских букв.

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

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

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

Новую группу надо добавлять не "в конец" (как третью), а "в середину" - так чтобы она была второй, а "правильная" кириллица - третьей.

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

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

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

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

То есть соответствующая строчка в нашем "полном описании конфигурации" будет выглядеть не как

xkb_symbols { include "en_US(105)+ru+new-ru" };
а немного короче
xkb_symbols { include "en_US(105)+new-ru" };

Итак. Берем в свою директорию файл symbols/ru и начинаем его "корежить".
Надо заметить, что, скорее всего в нем вы обнаружите три блока -

xkb_symbols "toggle" {...};
xkb_symbols "shift_toggle" {...};
xkb_symbols "basic" {...};

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

Обычно, если у вас в полной конфигурации указан просто файл ru, загружается первый блок. И переключателем "рус/лат" становится клавиша CapsLock.

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

А сейчас я предлагаю просто выкинуть ("вычистить") два первых блока и оставить только блок "basic". А переключатель допишем потом прямо в блок "basic", или "приплюсуем" подходящий блок из файла symbols/group (в нем описано аж шесть разных способов переключения).

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

key <AB01> {	[		z,		 Z	],
		[     Cyrillic_ya,     Cyrillic_YA	]	};

мы должны описать как
key <AB01> {	[		z,		 Z	],
		[            0xd1,            0xf1	],
		[     Cyrillic_ya,     Cyrillic_YA	]	};
Естественно, первый код соответсвует маленькой букве, а второй - большой.

Как подобрать коды? Ну, во-первых, по названию букв можно догадаться - какую русскую букву они имеют ввиду и, если у вас есть под рукой табличка - какой русской букве, какой код koi8-r соответствует, просто переписать оттуда.

А во-вторых, могу подсказать, что младший байт кода Cyrillic на самом деле соответствует коду этой буквы в koi8, а в старшем байте всегда шестерка.

Поэтому, можно взять файл, в котором описываются числовые значения для кодов типа Cyrillic_* - это файл /usr/X11R6/include/X11/keysymdef.h. И списать соответствующие коды оттуда, отбрасывая первую шестерку.

Особо ленивые могут взять готовый файл здесь.

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

Во-первых, надо заметить, что все варианты переключателей используют для своих целей специальный символ - ISO_Next_Group, а его семантика, описанная в xkb_compat такова, что он просто перебирает все возможные группы. То есть, при нажатии клавиши (или комбинации клавиш) с таким символом просто текущее значение группы увеличивается на единицу, а когда счетчик доходит до последней группы, он просто возвращается на первую (см. "Внутренности":"Методы выравнивания номера группы").

Таким образом тем же самым перключателем "рус/лат" мы можем последовательно перебирать все три группы.

Вы можете выбрать ваш любимый способ переключения из файла symbols/group и "приплюсовать" его к описанию xkb_symbols, например,

xkb_symbols { include "en_US(105)+new_ru+group(shift_toggle)" };

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

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

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

Для того, чтобы этого не происходило, надо бы "отцепить" реальный модификатор Lock от этой клавиши. К сожалению, "привязка" модификатора к символу Caps_Lock "зарыта" глубоко в файлах, которые "инклюдятся" в en_US. А отменить это присвоение в дополнительных файлах уже нельзя.

Поэтому, чтобы не "перелопачивать" все файлы, которые неявно включаются в нашу полную конфигурацию, лучше просто убрать символ Caps_Lock из описания клавиши <CAPS>.

Если вам жалко расставаться с этой функцией - "подвесьте" ее на какую-нибудь другую клавишу. А если вы используете для "рус/лат" другой способ - то и описанной проблемы у вас не будет.

Итак. Если ваш любимый способ переключения - клавиша CapsLock, то последнее, что нам надо сделать - не "приплюсовывать" этот способ из файла symbols/group (там эта клавиша с кодом Caps_Lock), а просто вписать в нашу новую раскладку определение для клавиши <CAPS> -

key <CAPS> { [ISO_Next_Group] };

Теперь можно прегрузить конфигурацию программой xkbcomp и посмотреть результат.

Кстати, забавно, что "старые" программы теперь работают когда у вас включена и вторая группа и третья. Потому, что они в обоих случаях видят в "состоянии модификаторов" модификатор, который указывает, что включена альтернативная группа, а коды символов всегда берут из второй группы. То есть, для них не заметна разница между двумя состояниями XKB (включена вторая или третья группы).
Интересно, что некоторые "новые" программы, например - xterm, тоже правильно работают с обоими группами. Потому, что... фиг его знает - почему :-)

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

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

"Вариации на тему" - переключатели "рус/лат" (и еще раз - "рус").


Иван Паскаль [email protected]