xatk — эффективное переключение окон
TL;DR см. Как пользоваться
Предыстория
Когда-то я, как большинство нормальных людей, переключался между окнами при помощи списка открытых окон на панели. Затем я у кого-то подглядел волшебное сочетание клавиш Alt-Tab, которое позволяло переключаться с помощью клавиатуры, а также благодаря расположению окон в виде стека выбирать недавно используемые окна за меньшее количество нажатий. Очень скоро после того, как я окунулся в мир Linux, я обнаружил замечательную программу wmctrl, позволяющую выполнять различные действия над окнами из командой строки или же, что более интересно, по сочетанию клавиш. Одним из таких действий является активация окна, которое задаётся по названию, классу или идентификатору. С её помощью а также xbindkeys я создал сочетания клавиш для переключения на определённые часто используемые окна. Обычно это было более предпочтительным вариантом, чем переключение по Alt-Tab или Alt-Esc, так как большинство окон можно было активировать всего по одному нажатию клавиш. Решение не было универсальным, так как не все окна имели собственные сочетания клавиш. К тому же, не было возможности переключиться на определенное окно одного и того же приложения (wmctrl выбирал первое подходящее совпадение). Для этого приходилось переключаться на первое окно группы, а затем «листать» окна этой группы по Alt-F6 (стандартное сочетание metacity).
Так родилась идея написать небольшой скрипта, который бы динамически при появлении нового окна назначал ему сочетание клавиш. При этом хотелось, чтобы сочетания для одних и тех же окон оставались постоянными. Предпочтительные клавиши можно было бы выбирать из названия класса окна, когда как у всех сочетаний клавиш был бы один и тот же модификатор. Например, окно Firefox бы поднималось по Mod+F, а Emacs — по Mod+E. Для второго и третьего окон Firefox можно было бы присвоить сочетания Alt+F+G и Alt+F+H, так как G и H находятся близко к F и их легче нажимать. Очень не хотелось создавать двухуровневые сочетания для переключения к первому окну, так как эта операция наиболее часто выполняемая. Как же одновременно привязать Alt+F и Alt+F+G к различным действиям? Просто. Alt+F можно повесить на отжатие клавиши F и выполнять данное действие только в случае, если другое сочетание не будет нажато. Подобные сценарии можно обрабатывать с помощью xbindkeys, не в последнюю очередь потому что к нему можно составлять конфигурацию на полноценном языке программирования — Guile (одна из реализаций Scheme).
Средства
Первой идеей было приспособить замечательные приложения xbindkeys, wmctrl и devilspie1 на выполнение данной задачи. Вскоре стало ясно, что это накладывает много ограничений: отсутствие сигнала закрытия окна для освобождения соответствующего сочетания клавиш, необходимость запуска нового экземпляра xbindkeys, невозможность слежения за изменением заголовков окон (для помещения туда информации о сочетании клавиш). В добавок, этот метод требует слишком много зависимостей, как для такой простой задачи.
Из любопытства я начал почитывать документацию к Xlib, EWMH, чужой код в поисках всех необходимых вещей для реализации задуманного, хотя по правде говоря, мне изобретать велосипед вовсе не хотелось. Но всего же, имея немного свободного времени и получив некоторое представление об управлении оконами в x11, все же начал писать. В первую очередь из-за собственной лени вопрос выбора языка программирования вовсе не стоял — начал я писать на Python, для которого существует реализация клиентского протокола Xlib — проект с вполне оправданным названием python-xlib.
Реализация
Так как классы окон чаще всего соответствуют именам приложений, то было решено использовать их по умолчанию в качестве последовательностей символов, по которым подбираются сочетания клавиш. Данное имя я незамысловато назвал «абстрактным именем окна» (awn). Другой источник, откуда можно получить имя — заголовок окна. В результате, я пришел к созданию отдельной секции правил в конфигурационном файле (по-умолчанию ~/.xatkrc) с ini-подобной структурой. В данной секции пользователь задает, как классы и заголовки будут преобразоваться в абстрактные имена при помощи регулярных выражений. Так, указав в секции правил
class.(xterm|rxvt|gnome-terminal) = terminal
окна с классами xterm, rxvt, gnome-terminal получат awn terminal. Символы t, e, r, m, i, n, a, l будут поочередно перебираться до первого незанятого. Если же все заняты, xatk выберет свободный символ на свой вкус. В случае отсутствия подходящего правила, в качестве awn будет взят класс окна.
Второе применение awn в том, что по нему осуществляется группировка окон. В данном случае, если открыть поочередно xterm, потом rxvt и gnome-terminal, то вероятнее всего, их сочетания будут MOD+T, MOD+T+Y и MOD+T+U соответственно. Если данный эффект не нужен, достаточно указать разные абстрактные имена. Например, terminal1, terminal2 и terminal3. Цифры 1, 2, 3, как и другие не латинские алфавитные символы, не будут участвовать при формировании сочетаний клавиш.
Во время написания части программы, отвечающей за обработку сочетаний клавиш, в голову пришла еще одна идея — переключение между окнами одной группы. Данный эффект достигается поочерёдным нажатием на клавишу группы, например MOD+T+T+T+....
На данном этапе существовала проблема, которая заключалась в том, что сочетания клавиш для окон одних и тех же приложений будут постоянно меняться. Например, при использовании программ Icedove и Iceweasel, сочетание MOD+I займет то приложение, которое будет раньше запущено, второму достанется MOD+C. При этом, чем больше окон используется, тем наложения все более вероятны. Первое решение проблемы, которое приходит в голову — позволить пользователю жестко назначать сочетания клавиш. Но данное решение опять возвращает нас к тому, против чего мы боролись: данный метод будет работать только для заранее определённых пользователем окон.
Другая идея — вести историю пар «awn — клавиша». Если при появлении нового окна в истории уже содержится его абстрактное имя, то нужно взять его прошлую клавишу, если конечно она не занята. Поскольку история имеет свой размер, то программы, которые некоторое время не используются, забываются, а те, которые используются регулярно, имеют постоянное сочетание клавиш.
По умолчанию в качестве модификатора используется Super (он же Mod4 или Windows), на который, как правило, не посягают другие программы. Однако случаются и исключения2. В любом случае модификаторов должно хватить всем. Четыре реальных модификатора дают 15 комбинированных (когда несколько модификаторов нажато одновременно). Тем не менее вместо модификатора можно использовать и префикс, состоящий из нескольких модификаторов и клавиш. Например, в качестве префиксов могут выступать XF86h_RotateWindows (одна клавиша без модификатора) и Super+Alt+x+a+t+k. Список доступных клавиш можно получить, выполнив
xatk --print-keys
По умолчанию, все заголовки окон снабжаются информацией о сочетании клавиш, по которому данное окно активизируется, делая изучение комбинаций клавиш более простым. xatk вынужден следить за всеми изменениями в заголовках окон, чтобы контролировать наличие в заголовке соответствующей информации. Это может привести к нежелательным последствиям, если какое-то другое приложение делает с ними примерно то же, что и xatk. На данный момент единственным решением является отключение опции модификации заголовков окон.
Из других возможностей xatk, можно отметить:
- поддержка QWERTY и Dvorak клавиатур (это позволяет генерировать более удобные сочетания клавиш для окон, не являющихся первыми в группе);
- возможность отключения группировки окон, а вместе с ней и многоуровневых сочетаний клавиш;
- выставление формата заголовков окон;
- переключение на рабочий стол, где находится активное окно, или перемещение окна на текущий рабочий стол;
- пропуск сочетаний клавиш, используемые другими программами.
Как пользоваться
Для работы xatk необходимо, чтобы были установлены Python 2.x (x >= 6) и python-xlib.
xatk работает в качестве демона. Для этого достаточно ее запустить без параметров:
xatk
Если никаких ошибок программа не выдала, в заголовки окон добавились сочетания клавиш (по умолчанию в виде /x/), то теперь для переключения к окну x необходимо нажать Super+x. По нажатию Super+x+y поднимется окно с пометкой /xy/, а повторные нажатия x при удержании модификатора приведет к циклическому переключению окон группы x.
Для смены модификатора (префикса) сочетаний клавиш, раскладки клавиатуры (QWERTY на Dvorak), правил или других опций предварительно необходимо создать или отредактировать файл ~/.xatkrc. Для создания шаблона со стандартными значениями опций достаточно выполнить следующее:
xatk --print-defaults > ~/.xatkrc
Редактируем необходимые опции и запускаем.
Выход из программы на данный момент осуществляется только по сигналу SIGTERM:
pkill -f xatk
При этом xatk обновит историю в файле ~/.xatkrc
, чтобы при следующем запуске
сочетания клавиш остались прежними.
Где достать и что читать
Страница xatk находится тут: http://code.google.com/p/xatk/
Страница загрузки: http://code.google.com/p/xatk/downloads/list
Чуть более подробно о программе можно узнать из вики-страниц, копия которых находится в папке doc в архиве с программой.
Больше информации по настройке можно получить из ~/.xatkrc (созданному
командой xatk --print-defaults
).
Список параметров запуска xatk традиционно можно получить, указав опцию -h
или
--help
.
Вопросы, комментарии, пожелания можно задавать тут, на баг-трекере или же здесь в комментариях.
Обновление: xatk 0.1 — первая стабильная версия переключателя окон
-
Основная функция devilspie — выполнение различных действий над окнами при их появлении. devilspie бы мог сообщать нашей программе о появлении нового окна, и после чего бы она указывала xbindkeys новое сочетание клавиш. ↩
-
Релиз GNOME 3 увидел свет в день выхода xatk, так что следует полагать, они попросту не успели устранить этот конфликт. ↩
Комментарии