Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР 109, ЯНВАРЬ 2008 г.

Нихт ферштейн

Юрий «bober» Раззоренов

Хакер, номер #109, стр. 094

(zloy.bobr@gmail.com)

Учим пингвина понимать мультимедийные клавиши

Большинство современных клавиатур снабжено мультимедийными клавишами, да и мышки уже имеют от трех до семи кнопок. На диске, идущем в комплекте, или на сайте производителя доступны драйвера и всяческие полезные программы только для Windows. Всем известно, что Linux славится своей возможностью настроить систему «под себя», если, конечно, знать, где и что настраивать. Наша задача - научить пингвина работать с дополнительными батонами.

Определение скан-кода клавиш

Чтобы ты там не нажимал на своей клавиатуре, X-серверу и ядру, в общем-то, все равно, что на ней написано или нарисовано. Их интересует исключительно скан-код кнопки, причем иксы сначала считывают таблицу кодов клавиш ядра, а затем уже код клавиши привязывается к собственной таблице кодов. Если в Windows проблемы настройки мультимедийных клавиш в консоли как таковой не существует, то в Linux приходится отдельно настраивать реакцию на нажатие кнопок в консоли и в X-Window.

Чтобы узнать код клавиши, следует использовать утилиту xev, входящую в состав Х-сервера. После ее запуска появляется окно Event Tester, теперь последовательно нажимаем клавиши, запоминая выдаваемый код:

$ xev

...

KeyRelease event, serial 31, synthetic NO, window 0x3e00001,

root 0x67, subw 0x0, time 279734676, (311,611), root:(1104,687),

state 0x2000, keycode 236 (keysym 0x1008ff19, XF86Mail), same_screen YES,

XLookupString gives 0 bytes:

XFilterEvent returns: False

KeyRelease event, serial 31, synthetic NO, window 0x2600001,

root 0x67, subw 0x0, time 265877259, (883,334), root:(886,358),

state 0x0, keycode 161 (keysym 0x0, NoSymbol), same_screen YES,

XLookupString gives 0 bytes:

XFilterEvent returns: False

Вывод может быть огромен, так как отслеживается каждое движение мышки при проходе над окном Event Tester. Клавишу описывает блок KeyRelease, в частности, значение keycode как раз и является скан-кодом, который мы хотим узнать. В приведенном примере нажаты две клавиши. Клавише с кодом 236 соответствует код клавиши для X-сервера, указанный в keysym, а также действие XF86Mail, которое в KDE запускает используемый по умолчанию почтовый клиент. Для клавиши с номером 161 код и действие не определены.

Возможна ситуация, когда клавиша нажимается, но ее скан-код не выдается. Это означает, что ядро не может найти соответствующее значение. В выводе «dmesg» должна быть такая строка:

Use 'setkeycodes 0xec <keycode>' to make it known.

То есть тебе предлагают установить скан-код клавиши самостоятельно при помощи «setkeycodes», при этом значение keycode выбрать очень просто. Переведи полученную цифру в десятичное число (большинство калькуляторов это умеют) и прибавь 128. В данном примере 0xec = 236, то есть получаем скан-код 364. Если есть сомнения, список задействованных и незадействованных скан-кодов можно просмотреть, запустив в консоли утилиту «getkeycodes» или «dumpkeys». Например, если вывод «getkeycodes | grep <код клавиши>» ничего не дал, значит, этот код можно смело использовать.

Помочь определить скан-код способна и утилита ХKeycaps (www.jwz.org/xkeycaps), которая является графическим фронт-эндом к Xmodmap.

В консоли программа xev, разумеется, не работает. Чтобы узнать скан-код, выдаваемый ядром, следует использовать утилиты «showkey», либо «getkeycodes»:

$ showkey

клавиатура была в режиме UNICODE

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

0xe0 0x6c 0xe0 0xec

Первые две цифры соответствуют нажатой клавише, вторые - когда она отпущена.

Настройка привязки скан-кодов в X-Window

Итак, скан-коды теперь у нас есть, нужно указать Х-серверу, что он собственно должен делать при нажатии этой клавиши, то есть присвоить ей символьное имя. Список символьных имен приведен в файле заголовков XF86keysym.h. По умолчанию заголовочные файлы Х-сервера в современных дистрибутивах не устанавливаются. Чтобы увидеть его в Ubuntu, нужно установить пакет x11proto-core-dev, после чего данный файл будет лежать в каталоге /usr/include/X11. Как вариант, можно обратиться к CVS серверу X.Org (webcvs.freedesktop.org/xorg/proto/X11/XF86keysym.h?view=log&pathrev=XORG-CURRENT). Смотрим:

$ cat /usr/include/X11/XF86keysym.h

/*

* Keys found on some "Internet" keyboards.

*/

#define XF86XK_Standby0x1008FF10

#define XF86XK_AudioLowerVolume 0x1008FF11

#define XF86XK_AudioRaiseVolume 0x1008FF13

#define XF86XK_AudioPlay0x1008FF14

#define XF86XK_AudioStop0x1008FF15

#define XF86XK_Mail0x1008FF19

Если сравнить последнюю строку с выводом xev, то увидим, что значения совпадают с клавишей с keycode 236 - keysym 0x1008ff19, XF86Mail (без суффикса XK_). Список всех доступных значений в том виде, каком они должны использоваться, найдешь в /usr/share/X11/XKeysymDB.

Составить свой вариант раскладки можно несколькими способами: создать описание своей клавиатуры или использовать Xmodmap. Последний способ самый простой, поэтому о нем и будем говорить далее. В домашнем каталоге пользователя создаем файл .Xmodmap, в который заносим желаемые значения:

$ mcedit ~/. Xmodmap

keycode 161 XF86Calculator

keycode 174 XF86AudioLowerVolume

keycode 176 XF86AudioRaiseVolume

keycode 162 XF86AudioPause

И так далее, принцип, думаю, ясен. Причем код клавиш можно заносить как в десятичном, так и шестнадцатеричном виде. По моим наблюдениям, коды большинства клавиш стандартизированы. Поэтому если ты один раз настроишь реакцию на нажатие клавиши и перенесешь файл на другой комп, есть вероятность, что на другой клаве реакция на нажатие также подписанной клавиши будет аналогичная. Пользователи рабочего стола Gnome с GDM могут прописать все эти строки в общесистемный файл /etc/X11/Xmodmap.

В других случаях нам еще нужно указать X-серверу, чтобы он использовал созданный файл. В разных дистрибутивах это реализовано по-разному, основная идея состоит в запуске команды «/usr/bin/xmodmap $HOME/.Xmodmap» при входе пользователя в систему или при старте Х. Тут уже каждый танцует, как хочет. В форумах предлагают использовать файл $HOME/.xsession (в некоторых дистрибутивах он может называться .Xsession), .xprofile или системный /etc/X11/Xsession. И боюсь, что это далеко не все возможные варианты. Давай посмотрим, как сделано в KUbuntu:

$ sudo grep -iR xmodmap /etc

В результате находим прелюбопытнейший файл /etc/X11/Xsession.d/80ubuntu-xmodmap, такого содержания:

$ cat /etc/X11/Xsession.d/80ubuntu-xmodmap

/usr/bin/xmodmap /usr/share/apps/kxkb/ubuntu.xmodmap || true

USRMODMAP="$HOME/.Xmodmap"

if [ -x /usr/bin/xmodmap ]; then

if [ -f "$USRMODMAP" ]; then

/usr/bin/xmodmap "$USRMODMAP" || true

fi

fi

То есть загружается содержимое файла ubuntu.xmodmap и пользовательский .Xmodmap, если он существует. Открыв в редакторе ubuntu.xmodmap, ты обнаружишь список keycode и сопоставленные символьные имена. Отсюда можно сделать вывод: если разработчик сообщает о том, что его дистрибутив поддерживает мультимедийные клавиатуры, то можно с большой долей вероятности найти подобный файл. В других дистрибутивах присутствует аналогичная система запуска пользовательских xmodmap файлов.

Теперь, когда символьные имена клавишам присвоены, можно назначать им желаемые действия. Некоторые оконные среды, вроде KDE, умеют отрабатывать действия по символьным именам. Так при нажатии кнопки с XF86AudioPlay начинает воспроизведение плеер, используемый по умолчанию. Чтобы установить нужную комбинацию, достаточно зайти в Центр Управления KDE - Региональные и специальные возможности - Комбинации клавиш (в KUbuntu ищи в System Setting — Keyboard & Mouse). Аналогичный пункт меню есть и в Gnome (можно просто вызвать gnome-keyboard-bindings) и XFce. Плюс некоторые программы, вроде Amarok, Konqueror, MPD, также умеют обрабатывать нажатия клавиш. В других средах, не имеющих графических средств настройки, скорее всего, потребуется ручное вмешательство в конфигурационные файлы. Например, чтобы в IceWM по нажатию клавиши с символьным именем XF86AudioPlay запускался проигрыватель XMMS, а при повторном он становился на паузу, в файл ~/.icewm, появляющийся после первого запуска, следует добавить строку:

$ mcedit ~/.icewm

key XF86AudioPlay xmms --play-pause

В Fluxbox строка для запуска проигрывателя будет выглядеть так:

$ mcedit ~/.fluxbox/keys

None XF86AudioPlay :ExecCommand xmms --play-pause

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

Настройка реакции в консоли

В консоли порядок действий несколько отличается. Как ты помнишь, вывод «dmesg» рекомендовал назначить клавишные коды с помощью команды «setkeycodes». Но здесь есть отличия, клавишных команд в консоли не может быть больше 128, следует выбирать значения от 0 до 127:

$ setkeycodes 0xec 118

Посмотреть свободные значения можно в файле текущей клавиатурной раскладки. В Ubuntu и всех дистрибутивах, базирующихся на Debian, обычно это /etc/console-setup/boottime.kmap.gz. Скорее всего, будут заняты все клавиши, но зачастую не все из них действительно задействованы. Если после запуска проблем с клавишами нет, заносим эту строку в один из стартовых скриптов, например, в /etc/init.d/rc.local.

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

{ plain | <modifier sequence> } keycode keynumber = keysym

То есть можно указать так:

# Переключение консоли на одну назад при нажатии на клавишу с кодом 105

keycode 105 = Decr_Console

# Переключение консоли на одну вперед при нажатии на <Alt> и клавишу с кодом 106

alt keycode 106 = Incr_Console

Но можно создавать и свои варианты, указывая команду в переменных:

keycode 120 = F100

string F100 = "/sbin/shutdown -h now\n"

Другими словами, по нажатию клавиши с кодом 120 будет выполнено действие, указанное в переменной F100, в нашем случае задано выключение компьютера. Вместо F100, естественно, можно использовать любое другое имя.

Теперь не менее важная часть - куда все это записывать. В документации и в многочисленных советах предлагается использовать текущий файл консольной раскладки (в моем случае - boottime.kmap.gz). Кстати, это единственный файл описания раскладок, доступный после установки KUbuntu, чтобы увидеть остальные варианты, следует установить пакет console-data. После чего в /usr/share/keymaps/i386/ можно обнаружить несколько подкаталогов с файлами внутри. Но если тебе понадобится перейти на другую раскладку (в Ubuntu и некоторых других дистрибутивах для этих целей используется файл /etc/default/console-setup, либо ~/.console-setup), все настройки нужно будет перенести в другой файл, что несколько не удобно. Если все-таки решишься на этот шаг, используй имеющиеся записи, как шаблон, ничего не записывая на первую позицию, а в конце не забудь оставить пустую строку.

Немного о ноутбуке

Пока мне не попадался ноутбук, скан-коды клавиш которого определить не удалось. Поэтому настройки здесь ничем не отличаются от описанных выше. Хотя есть один прием, о котором хотелось бы рассказать. Я считаю очень удобным в использовании режим гибернации, когда, включив компьютер, обнаруживаешь все на своих местах. Современные дистрибутивы, как правило, его поддерживают, хотя настройка, в общем-то, не сложна, достаточно установить пакет hibernate и переопределить необходимые параметры в конфигурационном файле. Единственное, каждый раз для перехода в этот режим нужно запускать скрипт /usr/sbin/hibernate, что не всегда удобно, хочется просто закрыть крышку ноутбука, а вновь включив питание, обнаружить все на своих местах.

Сделать это очень просто, используя демон acpid, который представляет собой нечто вроде пользовательского интерфейса, позволяющего управлять любыми событиями ACPI, доступными через /proc/acpi/event. При этом acpid читает набор конфигурационных файлов из каталога /etc/acpi/events/. Если пакет с демоном в дистрибутиве отсутствует, устанавливаем его из репозитария, последнюю версию можно взять с сайта phobos.fs.tum.de/acpi. После установки необходимо в каталоге /etc/acpi/events создать два файла: lid и power. Первый описывает реакцию на закрытие крышки, второй - на нажатие кнопки включения питания.

$ sudo mcedit /etc/acpi/events/lid

event=button/lid.*

action=/usr/sbin/hibernate

$ sudo mcedit /etc/acpi/events/power

event=button/power.*

action=/sbin/shutdown -h now

Это несколько упрощенные варианты, в KUbuntu найдешь более сложные скрипты. После чего требуется перезапуск демона acpid:

$ sudo /etc/init.d/acpid restart

Теперь при закрытии крышки ноутбука система будет впадать в спячку с выключенным питанием, а при нажатии на кнопку питания - выключаться. Просто и удобно.

Программы настройки

Если тебе не по душе возня с конфигурационными файлами, предлагаю несколько программ, которые помогут настроить работу мультимедийных клавиш. Например, первоначальное назначение программы Sven (sven.linux.kiev.ua) - настройка дополнительных клавиш на мультимедийной клавиатуре, но, начиная с версии 0.4, она научилась исправлять ошибки при наборе текста и изменять клавиатурную раскладку. Более того, даже если у тебя обычная клава, с ее помощью ты сможешь эмулировать мультимедиа-клавиши, использовав вместо них клавиатурные сочетания. Также можно назначить действия на определенные кнопки мыши. Понимает приблизительно 10000 русских слов и 9500 английских. Если программа не переключилась сама, то раскладку можно изменить и вручную, при помощи специально заданной клавиши (по умолчанию Break). Отдельной клавишей (Scroll Lock) можно изменять регистр слов (верхний, нижний, первая буква - верхний, остальные - нижний). Индикатор-переключатель раскладки клавиатуры запоминает свое состояние для каждого окна, поэтому, часто переключаясь между приложениями, тебе уже не нужно будет дополнительно изменять и раскладку. Программа имеет большие возможности, и я бы советовал на нее взглянуть. Все настройки производятся при помощи графической программы, построенной на GTK+ библиотеках. Sven тестировался в Linux, но, в принципе, должен работать и на *BSD системах. Используемый оконный менеджер не имеет значения.

Возможности KeyTouch (keytouch.sf.net) несколько скромнее, эта утилита применяется исключительно для настройки мультимедийных клавиш. Хотя с ее помощью можно любой клавише назначить свое действие, отличающееся от установок по умолчанию. На сайте программы, кроме исходных текстов и пакетов для некоторых дистрибутивов, можно найти готовые настройки для мультимедийных клавиатур большинства известных производителей.

Еще одно интересное решение - xbindkeys (hocwp.free.fr/xbindkeys/xbindkeys.html), позволяет присваивать любой кнопке клавиатуры и мышки любые команды, в том числе, и команды оболочки. Все настройки производятся в конфигурационном файле, который имеет простой и понятный формат.

Xneur - аналог Punto Switcher

Часто можно услышать мнение, что программ, автоматически переключающих раскладку клавиатуры, как это делает Punto Switcher и ей подобные, в Linux нет. Хочу бросить камень в огород саботажников. О Sven, который обладает подобной функциональностью, можно прочитать в этой статье, но есть еще и X Neural Switcher - XNeur (www.xneur.ru). Эта программа анализирует вводимые пользователем символы и, если их последовательность не характерна для текущего языка, переключает раскладку и переписывает последнее слово.

Функционально Xneur разделен на 2 части. Демон xneur считывает конфигурационные файлы, работает в фоне и собственно реализует все возможности программы. Для удобной настройки используется графический интерфейс, точнее два: gxneur написан с использованием библиотек GTK+, а kXNeur - интерфейс для KDE. Кроме исходных текстов, на сайте доступны пакеты для Debian, Ubuntu, ASP Linux, CentOS/RHEL, Fedora 7 и 8. Есть Xneur и в репозитарии ALT Linux.

Содержание
загрузка...
Журнал Хакер #151Журнал Хакер #150Журнал Хакер #149Журнал Хакер #148Журнал Хакер #147Журнал Хакер #146Журнал Хакер #145Журнал Хакер #144Журнал Хакер #143Журнал Хакер #142Журнал Хакер #141Журнал Хакер #140Журнал Хакер #139Журнал Хакер #138Журнал Хакер #137Журнал Хакер #136Журнал Хакер #135Журнал Хакер #134Журнал Хакер #133Журнал Хакер #132Журнал Хакер #131Журнал Хакер #130Журнал Хакер #129Журнал Хакер #128Журнал Хакер #127Журнал Хакер #126Журнал Хакер #125Журнал Хакер #124Журнал Хакер #123Журнал Хакер #122Журнал Хакер #121Журнал Хакер #120Журнал Хакер #119Журнал Хакер #118Журнал Хакер #117Журнал Хакер #116Журнал Хакер #115Журнал Хакер #114Журнал Хакер #113Журнал Хакер #112Журнал Хакер #111Журнал Хакер #110Журнал Хакер #109Журнал Хакер #108Журнал Хакер #107Журнал Хакер #106Журнал Хакер #105Журнал Хакер #104Журнал Хакер #103Журнал Хакер #102Журнал Хакер #101Журнал Хакер #100Журнал Хакер #099Журнал Хакер #098Журнал Хакер #097Журнал Хакер #096Журнал Хакер #095Журнал Хакер #094Журнал Хакер #093Журнал Хакер #092Журнал Хакер #091Журнал Хакер #090Журнал Хакер #089Журнал Хакер #088Журнал Хакер #087Журнал Хакер #086Журнал Хакер #085Журнал Хакер #084Журнал Хакер #083Журнал Хакер #082Журнал Хакер #081Журнал Хакер #080Журнал Хакер #079Журнал Хакер #078Журнал Хакер #077Журнал Хакер #076Журнал Хакер #075Журнал Хакер #074Журнал Хакер #073Журнал Хакер #072Журнал Хакер #071Журнал Хакер #070Журнал Хакер #069Журнал Хакер #068Журнал Хакер #067Журнал Хакер #066Журнал Хакер #065Журнал Хакер #064Журнал Хакер #063Журнал Хакер #062Журнал Хакер #061Журнал Хакер #060Журнал Хакер #059Журнал Хакер #058Журнал Хакер #057Журнал Хакер #056Журнал Хакер #055Журнал Хакер #054Журнал Хакер #053Журнал Хакер #052Журнал Хакер #051Журнал Хакер #050Журнал Хакер #049Журнал Хакер #048Журнал Хакер #047Журнал Хакер #046Журнал Хакер #045Журнал Хакер #044Журнал Хакер #043Журнал Хакер #042Журнал Хакер #041Журнал Хакер #040Журнал Хакер #039Журнал Хакер #038Журнал Хакер #037Журнал Хакер #036Журнал Хакер #035Журнал Хакер #034Журнал Хакер #033Журнал Хакер #032Журнал Хакер #031Журнал Хакер #030Журнал Хакер #029Журнал Хакер #028Журнал Хакер #027Журнал Хакер #026Журнал Хакер #025Журнал Хакер #024Журнал Хакер #023Журнал Хакер #022Журнал Хакер #021Журнал Хакер #020Журнал Хакер #019Журнал Хакер #018Журнал Хакер #017Журнал Хакер #016Журнал Хакер #015Журнал Хакер #014Журнал Хакер #013Журнал Хакер #012Журнал Хакер #011Журнал Хакер #010Журнал Хакер #009Журнал Хакер #008Журнал Хакер #007Журнал Хакер #006Журнал Хакер #005Журнал Хакер #004Журнал Хакер #003Журнал Хакер #002Журнал Хакер #001