Roman Cheplyaka

xmonad: функциональный оконный менеджер

Иван Веселов

Роман Чепляка

Содержание

1. Вступление

2. О чем мы не расскажем

3. Установка

4. Конфигурация

5. Сочетания клавиш

6. Алгоритмы компоновок

7. Строка статуса

8. ManageHooks

9. Другие полезные расширения

10. Сообщество

Опубликовано в журнале OpenSource, выпуски 27, 28, 29.

1. Вступление

Сегодня доступно множество самых разных оконных менеджеров, но большинство из них, вопреки названию (“manage” по-английски — “управлять”) перекладывают работу по управлению окнами на пользователя. Действительно, чтобы создать удобную для работы конфигурацию из нескольких окон, максимизируя при этом доступное пространство экрана, пользователь должен потратить ощутимое время на перемещение окон и изменение их размеров. Более того, с появлением очередного окна всю работу приходится проделывать заново. Многим это надоедает настолько, что они просто распахивают окна на весь экран и переключаются между ними, — но даже такая задача, как распахивание каждого нового окна, тоже требует дополнительных телодвижений.

Если какое-то действие приходится выполнять множество раз, хороший программист стремится его автоматизировать. Так возникли современные тайловые (от англ. “tile” — “черепица”, “плитка”) оконные менеджеры, которые берут на себя всю рутинную работу по управлению окнами. В каждый момент окна занимают весь экран, не перекрываясь и не оставляя зазоров.

Figure 1. XMonad


Как раз об одном из таких оконных менеджеров мы собираемся рассказать. Имя ему — xmonad (читается “икс-монад”). Конечно, это не единственный тайловый оконный менеджер, но комбинация следующих характеристик и возможностей делают его уникальным:

  • стабильный, быстрый, лёгкий и простой
  • написан на чисто функциональном языке Haskell
  • возможность работы без использования мыши
  • поддержка Xinerama (многоэкранные конфигурации)
  • поддержка плавающих окон, табов и декораций
  • интеграция со средами GNOME и KDE
  • индивидуальные компоновки окон на каждом рабочем столе
  • огромная и постоянно растущая библиотека расширений
  • развёрнутая и подробная документация
  • большая и активная команда разработчиков, дружелюбное сообщество

xmonad состоит из двух частей: собственно ядро xmonad (которое само может быть использовано как очень минималистический оконный менеджер) и постоянно растущая библиотека расширений XMonadContrib (на момент написания статьи она насчитывала 127 отдельных модулей). Такое разделение позволяет ядру оставаться компактным и стабильным, и в то же время не ограничивает фантазию разработчиков.

В xmonad установлены высокие стандарты по отношению к качеству кода и документации. Каждая функция содержит четкое описание, а каждое расширение кроме того сопровождается примерами использования. Перед тем, как каждый патч поступит в репозиторий, он автоматически проверяется на наличие ошибок компиляции. Учитывая сильную статическую типизацию Haskell, это само по себе с большой вероятностью гарантирует, что код правильный. Кроме того, функции из ядра xmonad автоматически тестируются с помощью QuickCheck — более 100 различных инвариантов функций проверяются на случайным образом сгенерированных тестовых данных. Это обеспечивает высокую надёжность xmonad, так что даже используя разрабатываемую версию из репозитория darcs, вы ничем не рискуете.

2. О чем мы не расскажем

Об xmonad можно говорить долго (что мы и собираемся делать), и тем не менее всё охватить невозможно. Дадим сразу список вопросов, которые не будут освещены в статье, со ссылками на полезную информацию по ним.

  • Интеграция со средой GNOME: http://haskell.org/haskellwiki/Xmonad/Using_xmonad_in_Gnome
  • Интеграция со средой KDE: http://haskell.org/haskellwiki/Xmonad/Using_xmonad_in_KDE
  • Использование трея. Например, можно использовать stalonetray (http://stalonetray.sourceforge.net/)
  • Использование многоэкранных конфигураций. Никакой особой настройки для неё не требуется, если библиотека X11 для Haskell правильно собрана. Отметим, что многие пользователи находят модель xmonad (каждый монитор — отдельный рабочий стол) намного удобнее, чем модель других оконных менеджеров (один большой рабочий стол).
  • Композитные расширения: http://haskell.org/haskellwiki/Xmonad/Frequently_asked_questions#How_do_I_use_compositing_with_xmonad.3F
  • Установка “обоев” (фона рабочего стола). Для этого можно использовать любую программу, которая умеет выставлять фон корневого окна (root window), например, qiv или feh.
  • Использование urgencyHook для задания определённого действия оконного менеджера в ответ на то, что окно “хочет привлечь ваше внимание”. Это может быть полезным для отслеживания нотификаций различных программ. http://www.xmonad.org/xmonad-docs/xmonad-contrib/XMonad-Hooks-UrgencyHook.html

Figure 2. Многоэкранная конфигурация


Вообще, не стоит забывать, что в разделе часто задаваемых вопросов (http://haskell.org/haskellwiki/Xmonad/Frequently_asked_questions) вы сможете найти не только вопросы, но и ответы на них.

3. Установка

Сегодня многие операционные системы предлагают xmonad в виде готовых пакетов. Среди систем, которые дружат с xmonad, числятся {Open,Net,Free}BSD, Gentoo, Debian, Ubuntu, Arch, Fedora, Slackware и другие. Обратите внимание, что для полноценной конфигурации необходимо установить GHC (компилятор Haskell) даже в том случае, когда сам xmonad распространяется в бинарном виде.

Если для вашей системы xmonad не упакован, у вас есть отличный повод собрать его из исходников. Подробные инструкции приведены на сайте (http://xmonad.org/intro.html). В этом случае, как и при сборке многих других программ, перед вами будет выбор: собирать последний релиз (сейчас это версия 0.7, а версия 0.8 вот-вот выйдет) или разрабатываемую версию из darcs-репозитория (darcs — распределённая система контроля версий, используемая для разработки xmonad). Как уже было сказано, разрабатываемая версия достаточно стабильна, а старые ошибки исправляются в целом чаще, чем привносятся новые.

Ещё один важный шаг — установка документации. Если вы устанавливаете xmonad из пакетов для вашего дистрибутива, туда скорей всего уже включена сгенерированная документация. В противном случае (то есть вы не используете пакеты или там не оказалось документации), вы можете сгенерировать её прямо из исходных текстов командой

runhaskell Setup.lhs haddock

(предварительно установив программму haddock).

Если вы используете релиз-версию, то можно также читать документацию в интернете: http://xmonad.org/xmonad-docs/

4. Конфигурация

Итак, мы установили xmonad. Теперь хорошо бы попробовать его в действии!

Если вы входите в X из консоли с помощью команды startx или аналогичной, достаточно в $HOME/.xinitrc заменить вызов вашего оконного менеджера на xmonad (с указанием полного пути к программе, если это необходимо).

Если же вы используете менеджер дисплея (XDM/GDM/KDM/…), то аналогичные изменения надо внести в файл $HOME/.xsession (если у вас его нет, просто создайте и впишите туда xmonad). Создатели пакета могли позаботиться о том, чтобы в меню KDM или GDM появился тип сессии xmonad, но мы рекомендуем использовать файл запуска .xsession, для чего надо выставить в GDM/KDM тип сессии Default.

Поскольку xmonad ориентирован на работу с клавиатурой, рекомендуем ознакомиться с основными сочетаниями клавиш (ниже мы расскажем, как их можно изменить). Ознакомиться можно в man xmonad или по адресу http://xmonad.org/manpage.html. Основные из них: Alt+Shift+Return для запуска терминала, Alt+Shift+C для закрытия текущего окна, Alt+J и Alt+K для переключения между окнами, Alt+Shift+Q для выхода из xmonad.

Если вы не предпринимали особых действий, после запуска xmonad вы, вероятно, увидите однотонный фон вашего рабочего стола и никаких признаков наличия оконного менеджера. Сделать вывод об успешном запуске xmonad можно, запустив терминал указанным выше сочетанием клавиш. Дальнейшие инструкции помогут вам сделать xmonad более приветливым.

Вся конфигурация xmonad производится в конфигурационном файле $HOME/.xmonad/xmonad.hs. XMonad исповедует принцип “создай свой оконный менеджер сам” не только в переносном смысле (предлагая возможность гибкой настройки), но и в прямом — конфигурационный файл представляет собой программу на языке Haskell. Будучи скомпилированной, эта программа и будет вашим менеджером окон, а пакеты xmonad и xmonad-contrib, которые вы установили — это по сути библиотеки, которые делают создание своего оконного менеджера практически тривиальным.

Тем не менее, даже если вы первый раз слышите о языке Haskell, не стоит пугаться — о вас разработчики xmonad думают в первую очередь! Декларативность языка и широкие синтаксические возможности делают Haskell отличным языком для описания конфигурации, в чём мы вам и предлагаем убедиться.

Для начала заметим, что начинать с нуля нет никакой необходимости. Вашему вниманию предлагается тщательно документированный образец xmonad.hs (http://haskell.org/haskellwiki/Xmonad/Config_archive/Template_Config.hs) (если вы устанавливали xmonad из исходников, то этот же самый файл можно найти в директории с исходниками по адресу man/xmonad.hs). Кроме того, на вики-странице http://haskell.org/haskellwiki/Xmonad/Config_archive можно найти десятки конфигурационных файлов от пользователей xmonad.

Дадим минимум знаний о синтаксисе Haskell, который вам понадобится для написания конфигураций. Блочные комментарии заключаются между последовательностями “{-” и “-}” (фигурные скобки и дефис), а однострочные начинаются с “–” (два дефиса). Язык регистрозависимый, то есть путать большие и маленькие буквы нельзя. Кроме того, как и в языке Python, отступы и переводы строк играют определенную роль. Поэтому, для уменьшения количества ошибок рекомендуется всегда использовать пробелы вместо табуляций. Если у вас возникли проблемы, не стесняйтесь зайти в IRC на #xmonad в сети FreeNode и попросить помощи.

Теперь обсудим основные части конфигурационного файла. Если не считать комментарии, конфигурационный файл начинается с объявлений import. Каждое такое объявление должно располагаться в начале строки и говорит компилятору о необходимости подключить соответствующий модуль. Объявление

import XMonad

должно присутствовать в каждом конфигурационном файле. Кроме того, каждое расширение, которое вы будете подключать, как правило, потребует от вас добавления еще одного import’а.

Следующей важной частью xmonad.hs является строчка

main = xmonad defaults

Как вы помните, xmonad.hs является программой. Это объявление указывает, что при запуске программы надо исполнить функцию xmonad (которая и отвечает за управления окнами) с аргументом defaults — структурой данных, содержащей все настройки, такие как сочетания клавиш, компоновки окон и прочие.

Давайте присмотримся к определению defaults.

defaults = defaultConfig {
        terminal           = myTerminal,
        focusFollowsMouse  = myFocusFollowsMouse,
        borderWidth        = myBorderWidth,
        modMask            = myModMask,
        numlockMask        = myNumlockMask,
        workspaces         = myWorkspaces,
        normalBorderColor  = myNormalBorderColor,
        focusedBorderColor = myFocusedBorderColor,
        keys               = myKeys,
        mouseBindings      = myMouseBindings,
        layoutHook         = myLayout,
        manageHook         = myManageHook,
        logHook            = myLogHook,
        startupHook        = myStartupHook
    }

Здесь использована стандартная форма записи структур данных в Haskell. Слева от знака “=” стоят названия параметров, а справа — значения. В данном случае все значения представляют собой переменные, которые определены в других местах конфигурационного файла.

Обсудим смысл параметров.

terminal — строка, содержащая команду для вызова предпочитаемого вами терминала (например, “xterm”).

focusFollowsMouse отвечает за то, будет ли фокус ввода перемещаться, если вы перемещаете указатель мыши.

borderWidth, normalBorderColor и focusedBorderColor относятся к рамке, которая рисуется вокруг каждого окна.

modMask, numlockMask, keys и mouseBindings относятся к сочетаниям клавиш и будут объяснены ниже.

workspaces — список строк, которые будут идентифицировать ваши рабочие столы. По умолчанию они просто пронумерованы от 1 до 9. Вы можете выделять рабочие столы под отдельные задачи, например [“irc”, “mail”, “www”, “work”].

layoutHook содержит настройки компоновок окон. manageHook позволяет производить определённые действия при открытии нового окна. logHook поможет нам сделать строку статуса. startupHook может выполнять действия при старте xmonad. К этим параметрам мы ещё вернёмся.

5. Сочетания клавиш

Как и положено достойному оконному менеджеру, ориентированному на высокую производительность, xmonad обладает вполне богатым стандартным набором комбинаций клавиш, а также механизмами для их настройки и расширения.

Как правило, все сочетания клавиш, используемые xmonad, содержат в себе так называемую клавишу-модификатор, которая задаётся в конфигурационном файле. По умолчанию это левый Alt, однако многие пользователи находят удобным использование для этой цели клавиши Windows (на IRC-канале #xmonad даже выдвигалась шуточная идея о производстве наклеек с логотипом xmonad, которые можно смело наклеивать на клавишу Windows).

Обычно, в конфигурационном файле клавиша Windows обозначается значением mod4Mask, левый Alt — mod1Mask, правый Alt — mod3Mask. Узнать так ли это на вашей системе можно с помощью утилиты xmodmap, которая будучи запущенной без параметров, выдаст список текущих модификаторов вместе с их номерами.

Таким образом для того, чтобы назначить клавишу Windows в качестве модификатора, необходимо установить значение modMask равным mod4Mask, то есть:

modMask = mod4Mask

Обратите внимание, что после этого во всех сочетаниях клавиш, которые до этого приводились, Alt также изменится на новое значение modMask.

Рано или поздно каждому пользователю хочется расширить или переназначить какие-то из сочетаний клавиш, настроить их под свои нужды и привычки. Это может быть реализовано несколькими способами — стандартным (который использует для обозначения клавиш собственную нотацию xmonad, немного непривычную для стороннего взгляда) и способом, использующим расширение EZConfig, одно из многих расширений, входящих в состав XMonadContrib. EZConfig позволяет задавать клавиши в более дружественном стиле, используемом, например, в редакторе Emacs.

Итак, для того, чтобы воспользоваться любым расширением xmonad, его необходимо импортировать:

import XMonad.Util.EZConfig

Затем следует определить список пар “клавиша — действие”. В качестве примера мы рассмотрим как можно добавить сочетания клавиш “модификатор + стрелки влево” или “вправо” для переключения между окнами, дополнительные клавиши для перемещения и закрытия окон и некоторые другие мелочи:

myKeys = [ ("M-<Right>,    windows W.focusDown)
         , ("M-S-<Right>", windows W.swapDown)
         , ("M-<Left>,     windows W.focusUp)
         , ("M-S-<Left>,   windows W.swapUp)
         , ("M1-<F4>",     kill)
         , ("M-s h",       spawn "xmessage 'hello, xmonad!'")
         ]

Рассмотрим формат описания клавиш, который должен быть хорошо знаком пользователям Emacs: модификаторы и клавиши разделены дефисом, S — означает Shift, С — Сontrol, M — та самая выбранная клавиша-модификатор. Кроме того, M1, M2 и т.д. обозначают все остальные модификаторы (те, что вы можете видеть как mod1, mod2 и т.д., запустив утилиту xmodmap). Буквы и цифры обозначают сами себя, а всякие “хитрые” клавиши обозначаются через их названия в угловых скобках, то есть <Left>, <Enter>, <Escape>, <Home>, <F1> и т.д. (полный список можно посмотреть на странице с документацией EZConfig). Отметим, что возможно задание последовательности клавиш через пробел: “M-s h”, что означает нажатие сочетания mod+s и последующее нажатие клавиши h.

Сочетание клавиш соединяется в пару с назначенным ему действием с помощью круглых скобок:

("keys", action)

которые затем помещаются в список, обозначаемый квадратными скобками:

[ ("keys1", action1), ("keys2", action2) ]

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

myConfig `additionalKeysP` myKeys

Кроме того EZConfig предоставляет функцию для удаления неиспользуемых сочетаний клавиш removeKeysP, а также довольно полезную функцию checkKeymap, которая проверяет валидность задаваемых сочетаний клавиш и сообщает о повторах или синтаксически некорректно заданных сочетаниях.

6. Алгоритмы компоновок

Расположить окна на экране можно многими способами, которые в разной степени могут удовлетворять пользователя. Каждый алгоритм, располагающий окна, мы будем называть “алгоритмом компоновки окон” или просто “компоновкой” (по-английски “layout”). На момент написания статьи библиотека расширений XMonadContrib содержала более 40 различных компоновок, многие из которых также могут быть индивидуально настроены.

По умолчанию пользователю доступны три алгоритма компоновки: Tall, Mirror Tall и Full. Переключаться между ними можно комбинацией mod+Пробел. Заметим, что в отличие от dwm, xmonad позволяет для каждого рабочего стола устанавливать свою компоновку.

Full — простейший полноэкранный режим. Окно, которое в данный момент имеет фокус ввода, показывается на весь экран, а все остальные не видны.

Tall — компоновка, хорошо знакомая пользователям dwm. Экран делится на две части — так называемые главную (master) и побочную (slave). В главной области располагается не более чем заданное количество окон (по умолчанию одно окно), а все остальные располагаются в побочной области. Увеличить или уменьшить максимальное количество окон в главной области можно комбинациями mod+запятая и mod+точка соответственно. Кроме того, можно изменить соотношение между размерами главной и побочной частей комбинациями mod+l и mod+h.

Mirror Tall — компоновка, полностью аналогичная предыдущей, с той лишь разницей, что экран делится на две части не вертикально, а горизонтально.

Figure 3. Компоновка Circle и композитная прозрачность


В конфигурационной структуре данных за набор и настройки алгоритмов компоновок, доступных пользователю, отвечает параметр layoutHook. Вот как он определен по умолчанию:

myLayouts = tiled ||| Mirror tiled ||| Full
  where
     tiled   = Tall nmaster delta ratio
     nmaster = 1
     ratio   = 1/2
     delta   = 3/100

В первой строчке мы видим три алгоритма компоновки, разделённые “оператором выбора” ||| (три вертикальных черты). С Full все ясно — этот алгоритм не имеет никаких настроек. Алгоритм Tall имеет три параметра, здесь они названы nmaster, ratio и delta. nmaster — максимальное число окон в главной области по умолчанию. ratio — соотношение между главной и побочной частями экрана. Наконец, delta показывает, насколько это соотношение изменится после единоразового нажатия mod+l или mod+h. Таким образом, после подстановки значений переменных tiled будет определена как Tall 1 (1/2) (3/100), а Tall — это функция, которая принимает параметры алгоритма компоновки и возвращает сам алгоритм.

Теперь посмотрим на Mirror tiled. Мы помним, что tiled — это алгоритм компоновки. Таким образом, Mirror принимает алгоритм и возвращает другой, модифицированный алгоритм. Mirror как бы отражает компоновку относительно главной диагонали экрана, поэтому вертикально расположенные части переходят в горизонтально расположенные.

Mirror — не единственный модификатор алгоритмов компоновок. Например, модификаторы reflectHoriz и reflectVert из расширения XMonad.Layout.Reflect отражают компоновку в горизонтальном и вертикальном направлениях соответственно. Поэтому, если вы хотите получить, к примеру, компоновку с главной областью справа, а не слева, вы можете просто добавить в свой layoutHook алгоритм компоновки reflectHoriz tiled. Разумеется, каждый из модификаторов можно применять к любому из алгоритмов компоновок, в частности, модификаторы можно комбинировать: например, reflectHoriz (Mirror tall) даст вам компоновку с главной областью внизу.

Другим полезным семейством модификаторов являются декорации. Как вы заметили, одним из отличий xmonad от других популярных оконных менеджеров является полное отсутствие панелей, в которых обычно располагается заголовок окна. Подключение модуля XMonad.Layout.SimpleDecoration поможет исправить ситуацию. А именно, добавив алгоритм компоновки simpleDeco shrinkText defaultTheme tiled вы получите компоновку tiled, которая к тому же каждое окно снабдит панелью с заголовком этого окна. Вы можете изменять цвета и размер декораций с помощью параметра defaultTheme. Другой удобный декоратор — dwmStyle из модуля XMonad.Layout.DwmStyle — способен добавлять декорации, не тратя на них драгоценного пространства экрана. Попробуйте!

Пользователи Ion будут рады расширению XMonad.Layout.Tabbed, которое располагает декорации в виде табов.

Бывают также алгоритмы компоновок, специально приспособленные под определённые цели. Если вы используете многооконные программы обмена мгновенными сообщениями, такие как tkabber, pidgin или gajim, попробуйте расширение XMonad.Layout.IM. Настроив его, вы добьётесь того, что окно контактов (“ростер”) будет располагаться сбоку, во всю высоту экрана, а оставшееся пространство будет поровну поделено между окнами разговоров.

Figure 4. Компоновка для мгновенных сообщений


Несмотря на то, что концепция неперекрывающихся окон является ключевой для xmonad, плавающие окна также поддерживаются. Более того, xmonad автоматически распознает диалоговые окна и делает их плавающими. Для перемещения окна нужно перетащить его мышью, зажав клавишу mod (см. раздел “Сочетания клавиш”) и левую кнопку мыши, а для изменения размера — клавишу mod и правую кнопку мыши. Применение любой из этих операций над окном приведет к тому, что оно станет плавающим. Комбинация клавиш mod+t снимает с окна статус плавающего.

7. Строка статуса

Согласно одному из известных законов UNIX-философии программы должны делать одну вещь и делать её хорошо. Поэтому для того, чтобы выводить какую-либо информацию о текущем состоянии системы и оконного менеджера в частности, в xmonad и других тайловых оконных менеджерах используются специальные программы — строки статуса (status bar).

Как правило, с xmonad используется одна из следующих программ, показывающих строку статуса: dzen (http://gotmor.googlepages.com/dzen) и xmobar (http://code.haskell.org/~arossato/xmobar).

xmobar написан на Haskell и изначально предназначен для использования в xmonad, поэтому именно его мы рассмотрим подробнее.

На официальной странице проекта вы найдёте инструкции по сборке и установке xmobar. Отметим, что процесс сборки весьма типичен для Haskell-программ и практически идентичен сборке xmonad (та же последовательность из configure, make, install). Также русскоязычных пользователей может заинтересовать поддержка UTF-8, которую можно включить при конфигурации (этап configure), а также поддержка XFT.

Итак, xmobar успешно скомпилирован и установлен, займёмся его настройкой. Файл xmobar.config-sample представляет собой пример конфигурационного файла, который можно вполне успешно использовать практически без изменений. В нём можно задать позицию строки статуса, цвет и шрифт текста, а также указать различные мониторы, данные которых необходимо выводить. Примерами таких мониторов являются Weather, Network, Memory, Cpu, Battery, Thermal, Date, StdinReader, PipeReader и многие другие. Особый интерес представляют два последних, которые позволяют читать данные из стандартного входа (stdin) и из UNIX-конвейера (pipe) соответственно. PipeReader ещё пригодится нам для интеграции с xmonad.

Способов интеграции может быть несколько, но мы рассмотрим один из них, который предполагает запуск xmobar из .xinitrc или .xsession (в зависимости от того, какой именно файл вы используете для старта X) и взаимодействие с xmonad через конвейер (pipe). Рассмотрим интеграцию пошагово:

  1. Создаём конвейер для взаимодействия, например, в директории ~/.xmonad:

    mkfifo ~/.xmonad/pipe
  2. Добавляем в сценарий запуска X (.xsession или .xinitrc) xmobar и вывод из xmonad в новосозданный конвейер:

    xmobar &
    exec xmonad > ~/.xmonad/pipe
  3. Используем расширение XMonad.Hooks.DynamicLog в xmonad.hs для создания logHook:

    Как обычно, добавляем необходимый импорт:

    import XMonad.Hooks.DynamicLog

    Создаём свой logHook c настройками для xmobar по умолчанию (параметр xmobarPP):

    myLogHook = dynamicLogWithPP xmobarPP

    Указываем его в конфигурации:

    logHook = myLogHook
  4. Используем расширение XMonad.Hooks.ManageDocks в xmonad.hs для учёта пространства, используемого строкой статуса.

    Поясним подробнее: для того, чтобы строка статуса не перекрывалась окнами — ей необходимо выделить пространство на рабочем столе, что делается с помощью функции avoidStruts, которая должным образом модифицирует layoutHook. То есть вы можете написать в конфигурации следующее:

    layoutHook = avoidStruts myLayout

    Кроме того, необходимо учитывать место, занимаемое строкой статуса, при распределении пространства для нового окна. Для этого предназначен специальный manageHook, который называется manageDocks и объединяется с вашим manageHook с помощью оператора <+>. Таким образом, в вашей конфигурации это будет выглядеть так:

    manageHook = myManageHook <+> manageDocks
  5. Конфигурируем xmobar:

    Указываем позицию, в которой будет находиться xmobar (нужно указывать не-статическую позицию, например Top или Bottom):

    position = Top

    Запускаем монитор, читающий из конвейера и называющийся “log”:

    Run PipeReader "~/.xmonad/pipe" "log"

    Добавляем этот монитор в строку, которая будет выводиться xmobar:

    template = "%log% }{ %date%"
  6. Теперь всё готово для совместной работы xmonad + xmobar, перезапускаем X.

Как можно заметить, интеграция xmonad со строкой статуса — далеко не самый простой процесс, поэтому в разрабатываемой версии xmonad из darcs-репозитория уже существуют функции, сводящие базовую настройку для работы совместно со строкой статуса всего к одной строке:

main = xmobar xmonad

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

("M-b", sendMessage ToggleStruts)

Более подробно о раличных настройках и функциях DynamicLog, определяющих вид выводимой в строку статуса информации, можно прочесть в документации к DynamicLog.

8. ManageHooks

Обладая большим количеством рабочих столов, довольно легко в них запутаться, поэтому разумной идеей представляется использование осмысленного имени для каждого рабочего стола — например “web”, “mail”, “irc” и т.д. В таком случае довольно быстро запоминается, что для того, чтобы написать письмо — нужно нажать например mod+5, а чтобы перейти к любимому браузеру — нажать mod+2. Однако захочется ли вам каждый раз распределять вручную окна по соответствующим рабочим столам? Думаю нет, потому эту работу вполне можно поручить xmonad, который с честью справляется с заданием, используя так называемый manageHook.

manageHook — это функция, которая вызывается после создания каждого окна и позволяет произвести в ней определённые подготовительные действия с окном, например перемещение на нужный рабочий стол.

Для того, чтобы определить какое именно действие нужно совершить с окном (и нужно ли вообще что-либо совершать) его нужно “опознать”. Это можно сделать с помощью X-свойств каждого окна, таких как WM_CLASS, WM_NAME, WM_ROLE и прочих. Рассмотрим примеры того, как представляются данные свойства окон в конфигурационном файле xmonad:

className =? "Emacs"
title =? "Pidgin"
appName =? "Test"
(getStringProperty "WM_ROLE") =? "Roster window"

Каждое из этих свойств представляет собой значение типа Query Bool, то есть запрос, который возвращает булево значение в качестве ответа. Определить свойства нужного вам окна поможет утилита xprop, имеющаяся в стандартной поставке X. Например, выполнение команды xprop | grep WM_CLASS с последующим щелчком по окну терминала urxvt выдаст следующее:

WM_CLASS(STRING) = "urxvt", "URxvt"

Первое из этих значений (urxvt) — это appName, второе (URxvt) — className, а чтобы получить заголовок окна (title) нужно выполнить xprop | grep WM_NAME. Кроме того, функция getStringProperty позволяет использовать в запросе любое X-свойство, обладающее типом STRING.

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

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

Рассмотрим их на примерах:

  1. Сделать окно mplayer плавающим:

    className =? "MPlayer" --> doFloat

    Можно читать это как “если className окна равен MPlayer — то сделать его плавающим”.

  2. Разместить окно Firefox на рабочем столе web:

    className =? "Firefox-bin" --> doF (W.shift "web")

После того как мы создали несколько таких правил, их нужно объединить в список и сделать из них manageHook с помощью функции composeAll:

myManageHook = composeAll
    [ className =? "MPlayer"     --> doFloat
    , className =? "feh"         --> doFloat
    , className =? "Pidgin"      --> moveTo "im"
    , className =? "Firefox-bin" --> moveTo "web"
    , className =? "Emacs"       --> moveTo "emacs"
    , className =? "Epdfview"    --> moveTo "read"
    , className =? "Eclipse"     --> moveTo "dev"
    , className =? "VirtualBox"  --> moveTo "win"
    ]
      where moveTo = doF . W.shift

Здесь мы для удобства вводим вспомогательную функцию moveTo для переноса окна на заданный рабочий стол.

И, наконец, финальный аккорд: нужно позаботиться о том, чтобы наша функция myManageHook использовалась xmonad в качестве manageHook, это делается с помощью указания:

manageHook = myManageHook

в структуре данных defaults, отвечающей за конфигурацию (подробнее об этом см. в разделе “Конфигурация”)

9. Другие полезные расширения

Мы рекомендуем для повышения эффективности иметь сочетания клавиш для всех постоянно запускаемых программ. Тем не менее, иногда приходится запускать программы без сочетаний клавиш. Конечно, можно запускать ради этого терминал (или искать запущенный), но есть и более удобный способ. А именно, если импортировать модули XMonad.Prompt и XMonad.Prompt.Shell и привязать действие “shellPrompt defaultXPConfig” к свободному сочетанию клавиш, то это сочетание будет вызывать окно со строкой ввода для команд.

toggleBorder из расширения XMonad.Actions.NoBorders убирает рамку вокруг окна. Полезно, например, при просмотре фильма в mplayer. Также рамку можно отключить для всей компоновки с помощью расширения XMonad.Layout.NoBorders.

XMonad.Layout.PerWorkspace позволяет задавать для разных рабочих столов разные наборы компоновок.

XMonad.Actions.CopyWindow умеет дублировать одно окно на несколько рабочих столов.

XMonad.Layout.ResizableTile — компоновка с возможностью легко изменять размер окон, не делая их плавающими.

Конечно, все расширения перечислить в рамках этой статьи невозможно. Пройдитесь на досуге по списку расширений, почитайте описания, и вы наверняка найдете для себя что-нибудь новое и полезное!

10. Сообщество

Сейчас трудно в это поверить, но проекту xmonad всего чуть больше года. За это время число разработчиков возросло с 3 до 11, а количество людей, приславших свои патчи перевалило за 60.

Основными местами общения разработчиков и пользователей xmonad являются список рассылки и IRC-канал #xmonad в сети FreeNode (irc.freenode.net). На канале находятся более 100 человек, включая практически всех разработчиков. Сообщество, образованное вокруг xmonad, общепризнанно считается очень дружелюбным к новым пользователям. Если у вас возникли трудности при написании собственного конфигурационного файла, или вы не знаете, как реализовать нужную функциональность с помощью средств xmonad, — заходите и спрашивайте, и вам обязательно помогут более опытные пользователи. Ещё раз подчеркнём, что требовать от вас знания Haskell никто не будет, хотя для многих xmonad как раз послужил толчком к изучению этого интересного языка.

Figure 5. IRC-канал и список рассылки


Другой хорошей традицией является активное участие пользователей в процессе разработки. Если вы написали новое расширение, исправили ошибку или улучшили документацию, запишите изменения (darcs add, darcs record) и отправьте их в список рассылки (darcs send). Разработчики просмотрят ваш патч и с радостью его примут.