Динамические оконные менеджеры для меня все еще остаются довольно непривычными. Отталкивает сама концепция их работы. Мои рассуждения на эту тему можно найти в заметке Почему я пользуюсь Openbox? Но все же дадим шанс еще одному их представителю — dwm.
Сразу начну с того, что dwm — это сверх-компактное приложение. Даже конфигурация производится путем изменения исходных кодов и перекомпиляции пакета. Хотя я считаю, что это уже лишнее. На современном оборудовании выигрыш от такого решения окажется незаметным. С другой стороны, сборка dwm много времени не отнимает. Да и конфигурацию придется менять лишь на первых этапах затачивания этого менеджера под себя.
Далее я расскажу о своих впечатлениях от dwm. Укажу некоторые его особенности. И приведу небольшие примеры конфигураций, которые успел попробовать.
- Первый запуск dwm
- Запуск приложений в dwm
- Варианты компоновки и управление окнами в dwm
- Тайловый режим компоновки dwm
- Плавающий режим компоновки dwm
- Режим компоновки monocle в dwm
- Управление dwm в многоэкранной системе
- Статус-бар в dwm
- Настройка dwm через config.h
- Подготовительный этап перед настройкой dwm
- Изменение клавиши-модификатора в dwm
- Определение команд
- Привязка команд к комбинациям клавиш
- Правила отображения окон
- Перекомпиляции dwm с новым config.h
- Особенности поведения find_app.sh в dwm
- Выводы
Первый запуск dwm
В отличие от Openbox в верхней части экрана расположена стандартная панель. Только вот больше ничего и нет. Никаких меню или чего-то подобного dwm не предоставляет.
В панели мы видим цифры от 1 до 9. Они соответствуют девяти виртуальным рабочим столам. В документации dwm их называют тэгами (tags). Само собой, мы можем переключаться между ними. Либо с помощью мыши, либо клавишами Mod+N, где Mod — клавиша-модификатор (по умолчанию Alt), а N — номер тэга.
Также можно нажать Mod+0. Это приведет к объединению содержимого всех тэгов. При этом окна запущенных приложений будут умещены на одном экране.
Первая интересная особенность dwm в том, что для каждого монитора тэги независимы. Например, на 1-ом мониторе я могу перейти на 3-ий тэг. В это время на 2-ом мониторе ничего не изменится.
После тэгов идет обозначение текущего режима компоновки. Доступно три режима на выбор: tiled ( []=), floating ( ><>) и monocle ( [N]). О них мы поговорим чуть позже, когда научимся запускать приложения
Интересно, что режим компоновки распространяется сразу на все тэги. Но вновь каждый монитор живет своей жизнью. Например, на 1-ом можно выбрать тайловый режим, а на другом плавающий.
Вслед за режимом компоновки на панели отведено место для вывода заголовка активного окна. А в самом правом краю панели находится еще одно небольшое поле. В нем можно выводить полезную информацию. По сути, своеобразная встроенная альтернатива Conky. Скоро мы посмотрим на эту возможность поближе.
Запуск приложений в dwm
Для любого пользователя Linux основным приложением, конечно, является терминал. В dwm по умолчанию предусмотрена комбинация клавиш Mod+Shift+Enter для его запуска. Я уже давно привык к sakura, поэтому появившийся st не вызвал у меня большого энтузиазма. Но сменить используемый терминал не сложно, т.е. проблемой это считать нельзя.
Другая встроенная возможность dwm заключается в использовании лаунчера dmenu. Этот пакет нужно устанавливать отдельно. Во многом он напоминает gmrun, который я привык использовать в Openbox. Вызывается dmenu с помощью комбинации клавиш Mod+P.
В целом этого уже достаточно, чтобы хоть как-то можно было пользоваться системой. Но давайте посмотрим, что готов предложить dwm для повышения нашей эффективности.
Варианты компоновки и управление окнами в dwm
Начнем с главной фишки dwm.
Тайловый режим компоновки dwm
Этот режим используется в dwm по умолчанию. Однако его можно включить принудительно с помощью комбинации клавиш Mod+T.
Запустим сразу 5 терминалов, и посмотрим, что из этого получилось.
Экран условно поделен по вертикали на две части. Слева — главная область (в документации называется master), а справа — все остальное (называется стэком). Мы можем увеличивать и уменьшать вместимость главной области с помощью клавиш Mod+I и Mod+D соответственно. Например, увеличим вместимость до трех окон (нужно два раза нажать Mod+I).
Переключаться между окнами в текущем тэге можно с помощью клавиш Mod+J и Mod+K. Первая комбинация отвечает за перемещение вниз, а вторая — вверх. Если нажать Mod+Enter, то окно в фокусе перемещается на самый верх. Верхом считается первое окно в главной области. Если ее вместимость сделать равной единице, то окно будет занимать всю левую часть экрана. Похожий смысл эти клавиши имеют и в других режимах.
Также можно изменять размеры областей. Для этого предусмотрены клавиши Mod+H и Mod+L. Первая из них уменьшает главную область, а вторая увеличивает. Все это происходит за счет изменения ширины стэка. Например, нажмем пару раз Mod+H.
Плавающий режим компоновки dwm
Для перехода в этот режим используйте комбинацию клавиш Mod+F. После его активации окна станут открываться без привязки к сетке, как было в тайловом режиме.
Окнами можно управлять с помощью мыши при нажатой клавише Mod:
- Левая кнопка мыши для перемещения окна;
- Правая кнопка мыши для изменения размеров окна;
- Средняя кнопка мыши для включения/выключения плавающего режима для окна.
Окна в dwm не имеют рамок, поэтому закрыть приложение можно либо через его собственное меню. Либо с помощью комбинации клавиш Mod+Shift+C. Это относится ко всем режимам.
Плавающий режим можно использовать и для отдельных окон, не меняя общего режима компоновки. Для этого необходимо нажать Mod+Shift+Space. Повторное нажатие указанной комбинации возвращает окно обратно под управление текущего режима. Также можно воспользоваться мышью при нажатой клавише Mod, как описано выше.
Есть возможность пойти дальше и явно указать, какие приложения должны работать в плавающем режиме по умолчанию. До этого мы скоро дойдем.
Стандартных комбинаций клавиш для изменения размеров и положения окна в плавающем режиме при беглом просмотре документации я не увидел. Но для dwm существует много патчей. Думаю, там эти функции должны быть.
Режим компоновки monocle в dwm
Для перехода в этот режим нужно нажать Mod+M. Логика его работы довольно проста. В каждый момент времени отображается только одно окно. Остальные находятся под ним (кроме тех, что «плавают»). Для переключения между окнами можно использовать клавиши Mod+J и Mod+K.
Управление dwm в многоэкранной системе
Как я уже отмечал, все мониторы в dwm живут своей жизнью. Но можно их и подружить. В частности, с помощью мыши плавающие окна переносятся с одного экрана на другой.
Но можно обойтись и без мыши.
Чтобы сделать предыдущий монитор активным, нужно нажать Mod+<. Логично, что для перехода на следующий подойдет комбинация Mod+>. Переход осуществляется по циклу. Хотя если у вас два монитора, как у меня, то обе комбинации делают одно и то же. Т.е. просто переводят фокус с одного монитора на другой.
Для перемещения текущего окна на соседний монитор добавьте к комбинациям из предыдущего абзаца клавишу Shift. Т.е. Mod+Shift+< переносит окно на предыдущий монитор, а Mod+Shift+> — на следующий.
Кстати, подобные комбинации работают и для переноса окон с одного тэга на другой. Например, чтобы активное окно оказалось на 5-ом тэге, нажмите Mod+Shift+5.
Статус-бар в dwm
На панели dwm можно вывести любой текст. Это делается при помощи команды xsetroot. Например, чтобы просто отобразить Hello, world, введите на консоли следующее:
1 |
xsetroot -name "Hello, world" |
В правом верхнем углу текущего монитора появится соответствующая надпись.
Это, конечно, уже что-то, но нам бы хотелось выводить информацию поинтереснее. С задачей поможет справиться бесконечный цикл:
1 2 3 4 5 6 7 8 9 10 |
while true; do if [ "$( xset -q | awk -F \" \" '/Group 2/ {print($4)}' )" = "on" ]; then LAYOUT="RU"; else LAYOUT="EN"; fi; xsetroot -name "$LAYOUT | Vol: $( ~/.scripts/get_vol.sh ) | $( date +"%T" )" sleep 1s done & |
Этот скрипт каждую секунду выводит текущую раскладку, громкость и время.
Часть, касающуюся определения раскладки, я позаимствовал на wiki-странице Archlinux по dwm. Там же вы можете найти примеры скриптов для получения другой интересной системной информации.
Для определения громкости звука я использовал скрипт, который работает с pulseaudio:
1 2 3 4 5 6 7 |
#!/bin/sh if [[ $(pactl list sinks | grep -m 1 "Звук выключен:" | cut -d " " -f3) == "yes" ]]; then echo 0% else echo $(pactl list sinks | grep -m 1 "Громкость:" | tr -s ' ' | cut -d " " -f5) fi |
При желании вы можете выводить сюда любую интересующую вас информацию.
Чтобы каждый раз не набирать приведенный бесконечный цикл вручную, сохраните его в файл ~/.xprofile. Если вы используете экранный менеджер на подобии LXDM, GDM или KDM, то этого должно хватить.
Через этот же скрипт можно стартовать все приложения, которые должны быть запущены в начале работы с dwm. Не забывайте указывать в конце команд запуска знак &, чтобы процессы запускались в фоновом режиме.
Если вариант с ~/.xprofile не сработал, попробуйте поэкспериментировать с ~/.xinitrc. Добавьте указанный цикл в него.
Если у вас уже чешутся руки, чтобы добавить еще и Conky-панели, то не спешите. Прямой поддержки Conky в dwm нет. Запустить его в стандартном режиме можно, но получите вы явно не то, что ожидали.
Но есть обходные решения. Одно из них заключается в использовании dzen. Однако сейчас мы на нем останавливаться не будем.
Другое потенциальное решение заключается в использовании (или создании) специального dwm-патча для Conky. Этим вопросом я также пока что не занимался.
Настройка dwm через config.h
Самая хард-корная часть dwm осталась под конец Займемся изменением конфигурации и перекомпиляцией этого оконного менеджера.
РЕКОМЕНДУЕМ: Настройка dwm: Патчи
Подготовительный этап перед настройкой dwm
Я проводил тестирование под Archlinux, поэтому первая часть инструкций относится именно к нему и не подойдет для большинства других дистрибутивов.
Для начала нам понадобится пакет abs. Когда он будет установлен, запустим под root-ом соответствующую команду:
1 |
sudo abs |
На самом деле, использовать abs не обязательно. Можно просто скачать исходники dwm, и работать с ними. Однако с abs собранные пакеты окажутся под контролем pacman. А это никогда не помешает.
В результате запуска abs появится каталог /var/abs/. В нем есть несколько подкаталогов. В частности, действительным должен быть путь: /var/abs/community/dwm/. Скопируем этот каталог в /var/abs/local/:
1 |
sudo cp -R /var/abs/community/dwm/ /var/abs/local/ |
Далее сделаем себя владельцем новой копии каталога:
1 |
sudo chown -R $USER /var/abs/local/dwm/ |
В каталоге несколько файлов:
1 2 3 4 |
-rw------- 1 michael root 6,0K мар 1 21:17 config.h -rw------- 1 michael root 103 мар 1 21:17 dwm.desktop -rw------- 1 michael root 173 мар 1 21:17 dwm.install -rw------- 1 michael root 1,2K мар 1 21:17 PKGBUILD |
Нас интересует config.h. Откроем его. Это обычный заголовочный файл на Си. Пройдемся по основным настройкам, которые в нем можно поменять.
Изменение клавиши-модификатора в dwm
После запуска dwm мне сразу не понравилось, что в качестве клавиши-модификатора Mod используется Alt. Поэтому поменяем ее на Win. Для этого найдем следующую строку:
1 |
#define MODKEY Mod1Mask |
И заменим ее на эту:
1 |
#define MODKEY Mod4Mask |
Определение команд
Следующим шагом поменяем стандартный терминал st на sakura. Изменим следующую строку:
1 |
static const char *termcmd[] = { "st", NULL }; |
Таким образом:
1 |
static const char *termcmd[] = { "sakura", NULL }; |
Фрагмент выше определяет команду запуска терминала. Она записана в виде массива строк. Конец массива определяется с помощью NULL.
Если при запуске команды требуются дополнительные ключи, то каждый из параметров записывается в виде отдельного элемента массива. Например, добавим команды для получения скриншота и управления громкостью (здесь и дальше я использую абсолютный путь к своему домашнему каталогу, поэтому не забудьте сделать поправки):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* Команда для получения скриншота: */ static const char *scrotcmd[] = { "scrot", "/home/michael/screenshots/%Y-%m-%d-%T-screenshot.png", NULL }; /* Команды управления громкостью: */ /* Громкость выше на 5% */ static const char *volupcmd[] = { "amixer", "-D", "pulse", "sset", "Master", "5%+", "unmute", NULL }; /* Громкость ниже на 5% */ static const char *voldowncmd[] = { "amixer", "-D", "pulse", "sset", "Master", "5%-", "unmute", NULL }; /* Вкл/выкл звук */ static const char *volmutecmd[] = { "amixer", "-D", "pulse", "sset", "Master", "toggle", NULL }; |
Также в качестве эксперимента я добавил команды для быстрого запуска chromium и gvim при помощи скрипта find_app.sh. Его код приводится в одной из статей по настройке Openbox.
А вот и сами команды:
1 2 3 4 5 6 7 8 |
/* Определили путь к скрипту */ #define FIND_APP_SH "/home/michael/.scripts/find_app.sh" /* Команда запуска chromium: */ static const char *browsercmd[] = { FIND_APP_SH, "chromium", NULL }; /* Команда запуска gvim: */ static const char *vimcmd[] = { FIND_APP_SH, "gvim", NULL }; |
Привязка команд к комбинациям клавиш
Команды готовы, но нужно привязать их к клавишам. Для этого в config.h имеется массив keys:
1 2 3 4 5 6 7 |
static Key keys[] = { /* modifier key function argument */ { MODKEY, XK_p, spawn, {.v = dmenucmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, /* И т.д... */ }; |
Структура довольно проста. Сначала идут флаги клавиш-модификаторов. Затем основная кнопка для действия. Далее функция dwm. И наконец аргументы функции. Кроме функции spawn есть и другие, но мы их трогать не будем.
Свяжем наши команды со следующими клавишами:
- Mod+; — сделать скриншот scrotcmd;
- Mod+] — увеличить громкость volupcmd;
- Mod+[ — уменьшить громкость voldowncmd;
- Mod+Shift+M — Вкл/выкл звук volmutecmd;
- Mod+B — запустить браузер browsercmd;
- Mod+V — запустить GVim vimcmd.
Констант для кодов клавиш специальных символов в config.h не предусмотрено. Поэтому на помощь приходит утилита xev. Запустите ее в консоли. Затем нажмите нужную клавишу. Например, для ; можно увидеть следующее:
1 2 3 4 5 6 |
KeyPress event, serial 48, synthetic NO, window 0x4000001, root 0x2a3, subw 0x0, time 36945581, (1056,298), root:(1057,334), state 0x0, keycode 47 (keysym 0x3b, semicolon), same_screen YES, XLookupString gives 1 bytes: (3b) ";" XmbLookupString gives 1 bytes: (3b) ";" XFilterEvent returns: False |
Нам понадобится код 3b. Аналогично можно найти коды и для других специальных клавиш. В том числе и мультимедийных.
Также обращаю внимание, что по умолчанию в dwm на комбинацию Mod+B назначено действие «спрятать/показать панель». Мне эта функция не нужна, поэтому я просто удалил соответствующую строку инициализации:
1 |
{ MODKEY, XK_b, togglebar, {0} }, |
А вот, что я добавил:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
static Key keys[] = { /* modifier key function argument */ /* ... */ { MODKEY, 0x3b, spawn, {.v = scrotcmd } }, { MODKEY, 0x5d, spawn, {.v = volupcmd } }, { MODKEY, 0x5b, spawn, {.v = voldowncmd } }, { MODKEY|ShiftMask, XK_m, spawn, {.v = volmutecmd } }, { MODKEY, XK_b, spawn, {.v = browsercmd } }, { MODKEY, XK_v, spawn, {.v = vimcmd } }, /* ... */ }; |
По аналогии можно определить любые команды. А затем привязать их к нужным комбинациям клавиш по своему желанию.
Правила отображения окон
Также не могу пройти мимо настроек специальных правил размещения окон. Они определяются массивом rules:
1 2 3 4 5 6 7 8 9 |
static const Rule rules[] = { /* xprop(1): * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ /* class instance title tags mask isfloating monitor */ { "Gimp", NULL, NULL, 0, 1, -1 }, { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, }; |
Для идентификации окна проще всего использовать его класс, который стоит в качестве первого компонента. Кстати, прямо в config.h дается подсказка, как определить значение class для окна. Для этого воспользуйтесь утилитой xprop. В примере конфигурации по умолчанию приводятся классы Gimp и Firefox.
Параметр tags mask задает те тэги, к которым нужно привязать окно. Значение определяется с помощью бинарных флагов. Если указать ноль, то после запуска приложения его окно отобразится на активном тэге. Если указать 1, то на первом. Для отображения на втором подойдет значение 1 << 1. На третьем — 1 << 2. И так до 1 << 8 для девятого. Можно задать сразу несколько тэгов. Например: 1 | 1 << 3 для отображения сразу на 1-ом и 4-ом тэге. Допустимы и любые другие бинарные комбинации.
Следующий параметр isfloating указывает на то, должно ли окно по умолчанию появляться в плавающем режиме. Ноль означает «нет», а все остальные значения — «да». Плавающий режим в качестве режима по умолчанию хорошо подойдет для различных мессенджеров и других многооконных приложений.
Последний параметр monitor позволяет указать экран, на котором должно появляться окно. Значение -1 означает, что будет использован текущий монитор. При окно отобразится на первом мониторе. Для 1 — на втором. Для проверки других значений у меня не хватает мониторов, но логично предположить, что они также должны работать.
В качестве эксперимента добавим пару своих правил:
1 2 3 4 5 6 |
static const Rule rules[] = { /* Стандартные правила убраны для краткости */ { "chromium", NULL, NULL, 1 << 1, 0, 0 }, { "Gvim", NULL, NULL, 0, 0, 1 }, }; |
Перекомпиляции dwm с новым config.h
Теперь мы готовы к перекомпиляции dwm. Если вы собирали его из исходников, то просто выполните что-то на подобии make && make install. Я же воспользуюсь преимуществами abs.
Сначала необходимо перейти в каталог /var/abs/local/dwm/. А затем выполнить следующую команду:
1 |
updpkgsums && makepkg -fi |
Осталось только перезапустить dwm. Завершить сеанс можно с помощью комбинации клавиш Mod+Shift+Q. После повторного входа в dwm наша конфигурация вступает в силу.
Особенности поведения find_app.sh в dwm
Если приложение запускается в первый раз, то фокус оно автоматически не получит. Это не очень удобно. Особенно для chromium, поскольку мы привязали его к фиксированному тэгу.
Для запущенных приложений find_app.sh работает гораздо лучше. После нажатия комбинации клавиш окно не просто получит фокус, но и попадет в главную область тайлового режима.
Выводы
В целом dwm мне понравился. У него есть свои сильные и слабые стороны, к которым можно привыкнуть. Этот оконный менеджер предназначен для истинных ценителей минимализма.
Его мощь заключается в простоте добавления новых функций. Настройка dwm сводится к программированию. Вы сами дописываете код, чтобы получить именно то, что нужно. Также можно воспользоваться готовыми патчами, которые уже кто-то успел написать до вас.
Нельзя сказать, что идея программирования приложения под себя нова. В конце концов, практически для всех Linux-программ доступны исходные коды. Особенность dwm в его компактной архитектуре, предназначенной специально для изменений. При этом я сильно сомневаюсь, что многие пользователи решаются лезть в исходники Gnome или KDE
Написанием этой статьи я занимался под dwm. С другой стороны, вряд ли я перейду на него со своего Openbox
Свои вопросы и предложения по настройке dwm оставляйте в комментариях под этой статьей.