Динамические оконные менеджеры для меня все еще остаются довольно непривычными. Отталкивает сама концепция их работы. Мои рассуждения на эту тему можно найти в заметке Почему я пользуюсь Openbox?. Но все же дадим шанс еще одному их представителю - dwm.
Сразу начну с того, что dwm - это сверх-компактное приложение. Даже конфигурация производится путем изменения исходных кодов и перекомпиляции пакета. Хотя я считаю, что это уже лишнее. На современном оборудовании выигрыш от такого решения окажется незаметным. С другой стороны, сборка dwm много времени не отнимает. Да и конфигурацию придется менять лишь на первых этапах затачивания этого менеджера под себя.
Далее я расскажу о своих впечатлениях от 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. Скоро мы посмотрим на эту возможность поближе.
Для любого пользователя Linux основным приложением, конечно, является терминал. В dwm по умолчанию предусмотрена комбинация клавиш Mod+Shift+Enter для его запуска. Я уже давно привык к sakura
, поэтому появившийся st
не вызвал у меня большого энтузиазма. Но сменить используемый терминал не сложно, т.е. проблемой это считать нельзя.
Другая встроенная возможность dwm заключается в использовании лаунчера dmenu
. Этот пакет нужно устанавливать отдельно. Во многом он напоминает gmrun
, который я привык использовать в Openbox. Вызывается dmenu
с помощью комбинации клавиш Mod+P. Выглядит это следующим образом:
В целом этого уже достаточно, чтобы хоть как-то можно было пользоваться системой. Но давайте посмотрим, что готов предложить 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:
Для перехода в этот режим используйте комбинацию клавиш Mod+F. После его активации окна станут открываться без привязки к сетке, как было в тайловом режиме:
Окнами можно управлять с помощью мыши при нажатой клавише Mod:
Окна в dwm не имеют рамок, поэтому закрыть приложение можно либо через его собственное меню. Либо с помощью комбинации клавиш Mod+Shift+C. Это относится ко всем режимам.
Плавающий режим можно использовать и для отдельных окон, не меняя общего режима компоновки. Для этого необходимо нажать Mod+Shift+Space. Повторное нажатие указанной комбинации возвращает окно обратно под управление текущего режима. Также можно воспользоваться мышью при нажатой клавише Mod, как описано выше.
Есть возможность пойти дальше и явно указать, какие приложения должны работать в плавающем режиме по умолчанию. До этого мы скоро дойдем.
Стандартных комбинаций клавиш для изменения размеров и положения окна в плавающем режиме при беглом просмотре документации я не увидел. Но для dwm существует много патчей. Думаю, там эти функции должны быть.
Для перехода в этот режим нужно нажать Mod+M. Логика его работы довольно проста. В каждый момент времени отображается только одно окно. Остальные находятся под ним (кроме тех, что "плавают"). Для переключения между окнами можно использовать клавиши Mod+J и Mod+K.
Для общности привожу скриншот:
Как я уже отмечал, все мониторы в dwm живут своей жизнью. Но можно их и подружить. В частности, с помощью мыши плавающие окна переносятся с одного экрана на другой.
Но можно обойтись и без мыши.
Чтобы сделать предыдущий монитор активным, нужно нажать Mod+<. Логично, что для перехода на следующий подойдет комбинация Mod+>. Переход осуществляется по циклу. Хотя если у вас два монитора, как у меня, то обе комбинации делают одно и то же. Т.е. просто переводят фокус с одного монитора на другой.
Для перемещения текущего окна на соседний монитор добавьте к комбинациям из предыдущего абзаца клавишу Shift. Т.е. Mod+Shift+< переносит окно на предыдущий монитор, а Mod+Shift+> - на следующий.
Кстати, подобные комбинации работают и для переноса окон с одного тэга на другой. Например, чтобы активное окно оказалось на 5-ом тэге, нажмите Mod+Shift+5.
На панели dwm можно вывести любой текст. Это делается при помощи команды xsetroot
. Например, чтобы просто отобразить Hello, world
, введите на консоли следующее:
xsetroot -name "Hello, world"
В правом верхнем углу текущего монитора появится соответствующая надпись:
Это, конечно, уже что-то, но нам бы хотелось выводить информацию поинтереснее. С задачей поможет справиться бесконечный цикл:
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:
#!/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 осталась под конец :) Займемся изменением конфигурации и перекомпиляцией этого оконного менеджера.
Я проводил тестирование под Archlinux, поэтому первая часть инструкций относится именно к нему и не подойдет для большинства других дистрибутивов.
Для начала нам понадобится пакет abs
. Когда он будет установлен, запустим под root
-ом соответствующую команду:
sudo abs
На самом деле, использовать abs
не обязательно. Можно просто скачать исходники dwm, и работать с ними. Однако с abs
собранные пакеты окажутся под контролем pacman
. А это никогда не помешает.
В результате запуска abs
появится каталог /var/abs/
. В нем есть несколько подкаталогов. В частности, действительным должен быть путь: /var/abs/community/dwm/
. Скопируем этот каталог в /var/abs/local/
:
sudo cp -R /var/abs/community/dwm/ /var/abs/local/
Далее сделаем себя владельцем новой копии каталога:
sudo chown -R $USER /var/abs/local/dwm/
В каталоге несколько файлов:
-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 мне сразу не понравилось, что в качестве клавиши-модификатора Mod используется Alt. Поэтому поменяем ее на Win. Для этого найдем следующую строку:
#define MODKEY Mod1Mask
И заменим ее на эту:
#define MODKEY Mod4Mask
Следующим шагом поменяем стандартный терминал st
на sakura
. Изменим следующую строку:
static const char *termcmd[] = { "st", NULL };
Таким образом:
static const char *termcmd[] = { "sakura", NULL };
Фрагмент выше определяет команду запуска терминала. Она записана в виде массива строк. Конец массива определяется с помощью NULL
.
Если при запуске команды требуются дополнительные ключи, то каждый из параметров записывается в виде отдельного элемента массива. Например, добавим команды для получения скриншота и управления громкостью (здесь и дальше я использую абсолютный путь к своему домашнему каталогу, поэтому не забудьте сделать поправки):
/* Команда для получения скриншота: */
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.
А вот и сами команды:
/* Определили путь к скрипту */
#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
:
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
/* И т.д… */
};
Структура довольно проста. Сначала идут флаги клавиш-модификаторов. Затем основная кнопка для действия. Далее функция dwm. И наконец аргументы функции. Кроме функции spawn
есть и другие, но мы их трогать не будем.
Свяжем наши команды со следующими клавишами:
scrotcmd
;volupcmd
;voldowncmd
;volmutecmd
;browsercmd
;vimcmd
.Констант для кодов клавиш специальных символов в config.h
не предусмотрено. Поэтому на помощь приходит утилита xev
. Запустите ее в консоли. Затем нажмите нужную клавишу. Например, для ; можно увидеть следующее:
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 назначено действие "спрятать/показать панель". Мне эта функция не нужна, поэтому я просто удалил соответствующую строку инициализации:
{ MODKEY, XK_b, togglebar, {0} },
А вот, что я добавил:
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
:
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
означает, что будет использован текущий монитор. При 0
окно отобразится на первом мониторе. Для 1
- на втором. Для проверки других значений у меня не хватает мониторов, но логично предположить, что они также должны работать.
В качестве эксперимента добавим пару своих правил:
static const Rule rules[] = {
/* Стандартные правила убраны для краткости */
{ "chromium", NULL, NULL, 1 << 1, 0, 0 },
{ "Gvim", NULL, NULL, 0, 0, 1 },
};
Теперь мы готовы к перекомпиляции dwm. Если вы собирали его из исходников, то просто выполните что-то на подобии make && make install
. Я же воспользуюсь преимуществами abs
.
Сначала необходимо перейти в каталог /var/abs/local/dwm/
. А затем выполнить следующую команду:
updpkgsums && makepkg -fi
Осталось только перезапустить dwm. Завершить сеанс можно с помощью комбинации клавиш Mod+Shift+Q. После повторного входа в dwm наша конфигурация вступает в силу.
Если приложение запускается в первый раз, то фокус оно автоматически не получит. Это не очень удобно. Особенно для chromium
, поскольку мы привязали его к фиксированному тэгу.
Для запущенных приложений find_app.sh
работает гораздо лучше. После нажатия комбинации клавиш окно не просто получит фокус, но и попадет в главную область тайлового режима.
В целом dwm мне понравился. У него есть свои сильные и слабые стороны, к которым можно привыкнуть. Этот оконный менеджер предназначен для истинных ценителей минимализма.
Его мощь заключается в простоте добавления новых функций. Настройка dwm сводится к программированию. Вы сами дописываете код, чтобы получить именно то, что нужно. Также можно воспользоваться готовыми патчами, которые уже кто-то успел написать до вас.
Нельзя сказать, что идея программирования приложения под себя нова. В конце концов, практически для всех Linux-программ доступны исходные коды. Особенность dwm в его компактной архитектуре, предназначенной специально для изменений. При этом я сильно сомневаюсь, что многие пользователи решаются лезть в исходники Gnome или KDE :)
Написанием этой статьи я занимался под dwm. У меня он выглядит примерно так:
С другой стороны, вряд ли я перейду на него со своего Openbox :)
Свои вопросы и предложения по настройке dwm оставляйте в комментариях под этой статьей.
Anonymous:
Жду продолжение, очень уж надо настроить. Патчи.
Какой функционал интересует? Патчей много.
Требую вторую часть!
Ок. К следующему разу попробую настройки на свой вкус.
Интересно!
Ок. К следующему разу попробую настройки на свой вкус
Уступает ли dwm по функционалу i3-wm? Может ли делить таб по вертикали/горизонтали много раз?
Anonymous:
Уступает ли dwm по функционалу i3-wm?
Я не имею большого опыта работы с i3, но судя по доступной информации i3 в базовой поставке представляет собой более мощный оконный менеджер, чем dwm
Anonymous:
Может ли делить таб по вертикали/горизонтали много раз?
Без патчей такой возможности dwm не предоставляет. Однако дополнительные режимы компоновки достаточно легко добавляются
Снова вернулся на i3-wm, все же для меня он идеален. У dwm есть ряд недоработок в плане компоновки, а чтобы их исправить - нужно намного лучше изучить Си и переписать dwm.
Anonymous
Жду продолжение, очень уж надо настроить. Патчи.