Настраиваем сочетания клавиш в Linux

от автора


Раньше, у меня довольно часто возникала такая ситуация, когда одновременно работаешь в терминале и, например, в браузере.
После нескольких часов работы начинаешь путаться и в терминале вместо [Ctrl]+[Shift]+[C] нажимаешь [Ctrl]+[C], а в браузере наоборот. В итоге в терминале вы получаете прерывание а в браузере вместо ожидаемого эффекта у вас медленно прогружается дебаггер.
В один прекрасный момент меня это достало и я решил, что пора что-то менять…

До того как я переустановил на своей рабочей машине OSX на Linux, я успел привыкнуть к довольно приятной реализации сочетаний клавиш. А точнее к тому, что все основные операции, такие как «Вырезать», «Копировать» и «Вставить», все они используют кнопку [Cmd] (аналог кнопки [Win] на PC), а не [Ctrl], как это сделано по умолчанию в Linux и Windows. Это очень удобно, так как, повторюсь, если вы часто работаете в терминале, вы имеете единые сочетания клавиш для копирования и вставки как и во всех других приложениях, а прерывание всегда остается на своем месте [Ctrl]+[C].
Вы так же олучите профит от такого способа, если вы используете тайловый оконный менеджер, т.к. в большинстве случаев для использования стандартных операций и переключений между тэгами/окнами вам не придется снимать палец с вашего modkey

Конечно настраивать сочетания клавиш можно в конфигах каждого определенного приложения, но это слишком не удобно, к тому же не каждое приложение поддерживает такую настройку. По этому я решил просто забиндить стандартные сочетания клавиш на те, что нужны мне.
Т.е. нажимая [Win]+[C], ваш терминал будет думать, что вы нажимаете [Ctrl]+[Shift]+[C], а все остальные приложения, что [Ctrl]+[C].

Для реализации задуманного нам понадобятся программа, которая будет отслеживать наши нажатия, например xbindkeys или же можно воспользоваться штатными возможностями вашего оконного менеджера, и эмулятор нажатий на клавиши, их несколько: xdotool, xte и xvkbd.

Правда с первыми двумя у меня возникал один преинтереснийший глюк: если например вы нажимете [Win]+[A], эмулятор покорно передаст [Ctrl]+[A] в приложение, а приложение увидит что нажаты все три клавиши [Win]+[Ctrl]+[A] и не обработает такое сочетание. Этот весьма неприятный баг было не просто обнаружить, так как не помогала даже опция —clearmodifiers для xdotool, которая, казалось бы, специально для такого случая и создана. В xkdbb подобного поведения замечено не было.

Начнем, пожалуй с xbindkeys. Отключем все CapsLock, NumLock и прочие модификаторы, запускаем:

$ xbindkeys -k 

Открывается окошко, в окошке нажимаем сочетание [Win]+[A], в терминале получаем такой вывод:

"(Scheme function)"     m:0x40 + c:38     Mod4 + a 

где Mod4 — это наша клавиша [Win]. Это же можно использовать для написания конфига xbindkeys:

Открываем ~/.xbindkeysrc и пишем:

"xvkbd -xsendevent -text '\[Control_L]a'"     Mod4 + a 
Вариант для xdotool и xte

xdotool

"xdotool key --delay 0 --clearmodifiers ctrl+a"     Mod4 + a 

xte

"xte 'keydown Control_L' 'key A' 'keyup Control_L'"     Mod4 + a 

Теперь запустим xbindkeys:

$ xbindkeys 

И попробуем нажать [Win]+[A], эффект будет такой-же как и если бы вы нажали [Ctrl]+[A]

После того что вы убедитесь, что все работает, можно продолжить править кофиг, но перед следующим запуском нужно с начала завершить предыдущий процесс xbindkeys:

$ pkill xbindkeys 

Ок, с этим разобрались, но как нам передавать различные сочетания клавиш, при нажатии одних и тех же кнопок, в зависимости от программы с которой мы работем?
На помощь приходит все тот же xdotool с xprop, с помощью которых мы определяем является ли активное окно терминалом.

Давайте напишем простенький скрипт и положим его в /bin/copypaste.sh:

#!/bin/bash W=`xdotool getactivewindow` S1=`xprop -id ${W} |awk '/WM_CLASS/{print $4}'` S2='"URxvt"'                                               #Мой любимый терминал S3='"XTerm"'                                               #Мой второй терминал  if [ $1 = "copy" ]; then                                   # Проверяем аргумент на copy                                         if [ $S1 = $S2 ] || [ $S1 = $S3 ]; then                # Если это терминал     xvkbd -xsendevent -text '\[Control_L]\[Shift_L]\[C]'   # Отправляем [Ctrl]+[Shift]+[C]     else                                                   # Если нет      xvkbd -xsendevent -text '\[Control_L]c'                # Отправляем [Ctrl]+[C]     fi   fi  if [ $1 = "paste" ]; then                                  # Тоже самое для аргумента paste     if [ $S1 = $S2 ] || [ $S1 = $S3 ]; then     xvkbd -xsendevent -text '\[Control_L]\[Shift_L]\[V]'     else     xvkbd -xsendevent -text '\[Control_L]v'     fi   fi 

Используйте xprop, если вы не знаете какой класс использует ваша программа:

xprop 

и клик на окне

Не забываем сделать скрипт исполняемым:

# chmod +x /bin/copypaste.sh 

Работает он вот так:

$ copypaste.sh copy $ copypaste.sh paste 

Это же и допишем в наш конфиг ~/.xbindkeysrc:

"xvkbd -xsendevent -text '\[Control_L]a'"     Mod4 + a "copypaste.sh copy"     Mod4 + c "copypaste.sh paste"     Mod4 + v 

Подобным образом настраиваем сочетания для остальных клавиш.

Готовый конфиг:

для xbindkeys

~/.xbindkeysrc

"copypaste.sh copy"     Mod4 + c  "copypaste.sh paste"     Mod4 + v  "/usr/bin/xvkbd -xsendevent -text '\[Control_L]x'"     Mod4 + x  "/usr/bin/xvkbd -xsendevent -text '\[Control_L]z'"     Mod4 + z  "xvkbd -xsendevent -text '\\[Control_L]\\[Shift_L]\\[Z]'"     Shift+Mod4 + z  "/usr/bin/xvkbd -xsendevent -text '\[Control_L]q'"     Mod4 + q  "/usr/bin/xvkbd -xsendevent -text '\[Control_L]y'"     Mod4 + y  "/usr/bin/xvkbd -xsendevent -text '\[Control_L]a'"     Mod4 + a  "/usr/bin/xvkbd -xsendevent -text '\[Control_L]s'"     Mod4 + s  "/usr/bin/xvkbd -xsendevent -text '\[Control_L]o'"     Mod4 + o  "/usr/bin/xvkbd -xsendevent -text '\[Control_L]f'"     Mod4 + f  
для awesome 3.5

awful.key({ modkey,           }, "c",     function () awful.util.spawn("copypaste.sh copy") end), awful.key({ modkey,           }, "v",     function () awful.util.spawn("copypaste.sh paste") end), awful.key({ modkey,           }, "x",     function () awful.util.spawn("xvkbd -xsendevent -text '\\[Control_L]x") end), awful.key({ modkey,           }, "z",     function () awful.util.spawn("xvkbd -xsendevent -text '\\[Control_L]z'") end), awful.key({ modkey, "Shift"   }, "z",     function () awful.util.spawn("xvkbd -xsendevent -text '\\[Control_L]\\[Shift_L]\\[Z]'") end), awful.key({ modkey,           }, "y",     function () awful.util.spawn("xvkbd -xsendevent -text '\\[Control_L]y'") end), awful.key({ modkey,           }, "a",     function () awful.util.spawn("xvkbd -xsendevent -text '\\[Control_L]a'") end), awful.key({ modkey,           }, "s",     function () awful.util.spawn("xvkbd -xsendevent -text '\\[Control_L]s'") end), awful.key({ modkey,           }, "o",     function () awful.util.spawn("xvkbd -xsendevent -text '\\[Control_L]o'") end), awful.key({ modkey,           }, "f",     function () awful.util.spawn("xvkbd -xsendevent -text '\\[Control_L]f'") end), 

ссылка на оригинал статьи http://habrahabr.ru/post/266375/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *