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

Материал из rrv-wiki
Перейти к навигации Перейти к поиску

Читать об этом здесь, а это точная копия текста. Спасибо автору! Автор: Юрий «bober» Раззоренов

www.xakep.ru

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

Что бы ты там не нажимал на своей клавиатуре, 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. Смотрим:

$ cat /usr/include/X11/XF86keysym.h
/*
* Keys found on some "Internet" keyboards.
*/
#define XF86XK_Standby 0x1008FF10
#define XF86XK_AudioLowerVolume 0x1008FF11
#define XF86XK_AudioRaiseVolume 0x1008FF13
#define XF86XK_AudioPlay 0x1008FF14
#define XF86XK_AudioStop 0x1008FF15
#define XF86XK_Mail 0x1008FF19

Если мы сравним последнюю строку с выводом 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, она умеет исправлять ошибки при наборе текста и изменять клавиатурную раскладку. Более того, даже если у тебя обычная клава, с ее помощью ты сможешь эмулировать мультимедиа-клавиши, использовав вместо них клавиатурные сочетания. Также можно назначить действия на определенные кнопки мыши. Она понимает приблизительно 10 000 русских слов и 9 500 английских. Если программа не переключилась сама, то раскладку можно изменить и вручную, при помощи специально заданной клавиши (по умолчанию Break). Отдельной клавишей (Scroll Lock) можно изменять регистр слов (верхний, нижний, первая буква - верхний, остальные - нижний). Индикатор-переключатель раскладки клавиатуры запоминает свое состояние для каждого окна, поэтому, часто переключаясь между приложениями, тебе уже не нужно будет дополнительно изменять и раскладку. Программа имеет большие возможности, и я бы советовал на нее взглянуть. Все настройки производятся при помощи графической программы, построенной на библиотеках GTK+. Sven тестировался в Linux, но в принципе должен работать и на *BSD-системах. Используемый оконный менеджер не имеет значения.

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

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