DWM: Suckless переход с GNOME. Часть 2

от
Linux    dwm, xorg, archlinux

В прошлой статье, мы установили DWM (Dynamic Window Manager), и настроили его до состояния, в котором с ним можно более-менее адекватно работать. В этой части мы сделаем DWM еще более красивым и удобным.

И прежде чем мы начнем, я должен рассказать, что DWM имеет 3 режима отображения окон - tiling, floating и monocle. Принцип работы первого режима вы знаете. Второй - позволяет изменять размер окон перетаскиванием мышкой за края окон, накладывать окна друг на друга, в общем, симуляция не-тайлового WM. Monocle же просто отображает активное окно на весь экран. Дополнительные режимы могут быть установлены патчами, речь о них пойдет ниже.

Пакеты
Чтобы не захламлять статью словами "Установите то, установите это", в начале я напишу список пакетов (имена пакетов здесь для Archlinux, ищите альтернативы на свои дистры), которые пригодятся нам для дальнейшей настройки.

- sddm (gdm, lightdm, lxdm) - автостарт+фикс gnome-keyring
- sxhkd - хоткеи без перекомпиляции DWM
- slock или bslock (AUR либо Github если нужна кастомизация) - локскрин
- picom - прозрачность, фикс тиринга
- acpilight или xorg-xbacklight - изменение уровня подсветки. Выберите тот пакет, который у вас работает.
- xorg-xinput - фикс работы тачпада
- noto-fonts-emoji, xft-bgra (AUR) - цветные эмодзи в статусбаре
Настройка статусбара - тык.
Патчи - тык.

Внимание! Если вы НЕ стали использовать Display Manager для запуска DWM, то, при чтении данной статьи, используйте ~/.xinitrc вместо ~/.xprofile !!!

Автостарт + фикс gnome-keyring + фикс падения DWM при использовании некоторых fn-клавишВозможно, за время работы с DWM вы заметили, что в файловых менеджерах с поддержкой GVFS (nautilus/thunar/pcmanfm) у вас перестали запоминаться пароли, либо же запоминаются, но связка ключей не анлочится при старте сессии. Можно починить руками, а можно использовать Display Manager для таких целей. В конце-концов, Linux - это многопользовательская система, и если вашим компьютером пользуется кто-то еще, он, возможно, не захочет использовать DWM.
DWM не отображается в списке сессий DM, добавим его туда сами:
/usr/share/xsessions/dwm.desktop:
  1. [Desktop Entry]
  2. Encoding=UTF-8
  3. Name=Dwm
  4. Comment=Dynamic window manager
  5. Exec=dwm
  6. Icon=dwm
  7. Type=XSession
Включите ваш DM в автозапуск и настройте по своему усмотрению. Так как теперь мы используем DM вместо startx, скопируйте ~/.xinitrc в ~/.xprofile и удалите оттуда запуск DWM. Добавьте в .xprofile строки
  1. eval $(gnome-keyring-daemon --start)
  2. export SSH_AUTH_SOCK

Хоткеи без перекомпиляции DWMПроверьте, есть ли у вас переменная окружения XDG_CONFIG_HOME. Если нет, добавьте в .xprofile
  1. XDG_CONFIG_HOME=~/.config
  2. export XDG_CONFIG_HOME
Удалите все spawn-хоткеи из config.h DWM, так как теперь мы используем sxhkd для этой цели
Отредактируйте файл ~/.config/sxhkd/sxhkdrc. Вот пример:
  1. Print
  2.     flameshot gui
  3.  
  4. super + r
  5.     rofi -show drun
  6.  
  7. super + b
  8.     firefox
Напомню, что для того, чтобы узнать, как называется какая-либо кнопка, используйте xev из пакета xorg-xev
Добавьте в .xprofile
  1. sxhkd &
Внимание! Если вы НЕ используете DM, и используете sxhkd для запуска flameshot, вы так же должны запустить flameshot из .xinitrc, как было указано в первой части статьи, либо запускать sxhkd через dbus-launch!

ЛокскринЕсли вы используете slock, просто добавьте в конфиг sxhkd команду slock на удобную вам комбинацию. По-умолчанию, slock показывает серый экран, голубой экран при вводе, красный при неправильном пароле. Чтобы разблокировать экран, просто введите ваш пароль и нажмите Enter. Настройка цветов осуществляется путем редактирования config.h в исходном коде slock
bslock - продвинутый форк slock, позволяющий добавить текст на локскрин, и выводящий цвета, описанные выше, не на весь экран, а в небольшую панельку. Конфигурация осуществляется так же, как и в slock. Если у вас не отображается текст - измените значение переменной char *font_name. Доступные шрифты можно посмотреть командой bslock -f. Не забудьте добавить bslock в конфиг sxhkd

Прозрачность, фикс тирингаДобавьте в .xprofile
  1. picom &

Если вы обнаружили у себя тиринг (смотреть в полноэкранном режиме), то запускайте picom с ключом --experimental-backends
После запуска picom, pop-up меню и контекстные меню будут слегка прозрачными. Если вам это не нравится, уберите из конца /etc/xdg/picom.conf следющие строки:
  1. tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; };
  2. popup_menu = { opacity = 0.8; }
  3. dropdown_menu = { opacity = 0.8; }

Изменение уровня подсветкиДобавьте в конфиг sxhkd
  1. XF86MonBrightnessDown
  2.     xbacklight -dec 10
  3.  
  4. XF86MonBrightnessUp
  5.     xbacklight -inc 10
Введите команду
  1. ls /sys/class/backlight
Создайте и отредактируйте файл /etc/udev/rules.d/backlight.rules
Если у вас acpi_video0:
  1. ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="acpi_video0", GROUP="video", MODE="0664"
Если у вас intel_backlight:
  1. RUN+="/bin/chgrp video /sys/class/backlight/intel_backlight/brightness"
  2. RUN+="/bin/chmod g+w /sys/class/backlight/intel_backlight/brightness"
Добавьте себя в группу video
  1. sudo gpasswd -a имя_юзера video
Перезапустите сессию.

Фикс работы тачпадаЕсли у вас не работает тап (нажатие ЛКМ при касании тачпада), и/или вас неустраивает "неестественное" направление скроллинга:
Введите команду xinput и найдите имя своего тачпада.
Например:
  1. Virtual core pointer
  2. ⎜   ↳ Virtual core XTEST pointer
  3. ⎜   ↳ DELL09E1:00 04F3:30CB Mouse
  4. ⎜   ↳ DELL09E1:00 04F3:30CB Touchpad
  5. ⎜   ↳ PS/2 Generic Mouse
В этом случае тачпад называется "DELL09E1:00 04F3:30CB Touchpad"
Добавьте в .xprofile:
  1. touchpad="DELL09E1:00 04F3:30CB Touchpad"
  2. # Enable touchpad tap
  3. xinput set-prop "$touchpad" "libinput Tapping Enabled" 1
  4. # Enable natural touchpad scrolling
  5. xinput set-prop "$touchpad" "libinput Natural Scrolling Enabled" 1

Цветные эмодзи в статусбареПо-умолчанию, в DWM прописан запрет на использование xft-bgra (цветные шрифты). Чтобы его снять, найдите в drw.c следующие строки:
  1. FcBool iscol;
  2. if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
  3.     XftFontClose(drw->dpy, xfont);
  4.     return NULL;                                              
  5. }
и удалите их. В config.h в массив char *fonts[] пропишите используемые вами шрифты + NotoColorEmoji. Напомню, что посмотреть доступные шрифты можно комнадой fc-list. Пример:
  1. static const char *fonts[] =  { "Droid Sans Mono:size=10", "Noto Color Emoji:size=10" };
Не забудьте пересобрать DWM.

СтатусбарВот мы и подобрались к самому интересному - статусбар!
DWM выводит справа вверху имя корневого окна. Менять его можно командой xsetroot -name текст. Можете это проверить! Реализация статусбара заключается в том, что в бесконечном цикле (со sleep, конечно же, иначе вы полностью нагрузите одно из ядер CPU) генерируется строчка, которая передается в xsetroot. Благодаря тому, что в предыдущем пункте мы включили поддержку цветных эмодзи, мы можем использовать их как значки!
В начале этого пункта будут приведены некоторые сложные примеры получения статуса сети/локали/etc, а затем я покажу, как обновлять статусбар при изменении этих параметров при нажатии на хоткеи.

Создадим в домашней директории папку со скриптами, например ~/scripts, и добавим ее в PATH в .xprofile:
  1. PATH=$PATH:$HOME/scripts
  2. export PATH
Создадим скрипт bar.sh в этой папке. В начале, мы объявим компоненты нашего статусбара внутри функций, а затем вызовем все эти функции в одной строке, чтобы вывести их содержимое. Пример:
  1. #!/usr/bin/bash
  2.  
  3. layout(){
  4.     # Получаем значение LED для текущей раскладки
  5.     # Запустите xset -q | grep LED в терминале, чтобы посмотреть значения для каждой раскладки.
  6.     # Значения в этом примере действительны для раскладки us,ru
  7.     t=$(xset -q | grep LED)
  8.     code=${t##*mask:  }
  9.     if [[ $code -eq "00000000" ]]; then
  10.             result="EN"
  11.     else
  12.             result="RU"
  13.     fi
  14.     echo $result
  15. }
  16.  
  17. # Вывод даты в формате dd.MM.YYYY HH:MM
  18. fdate(){
  19.     date +"%x %H:%M"
  20. }
  21.  
  22. # Текущая громкость
  23. volume(){
  24.     full_str=$(amixer sget Master | grep Left: )
  25.     state=${full_str##*\[}
  26.     if [[ $state == "off]" ]]; then
  27.             echo off
  28.     else
  29.             state=${full_str#*\[}
  30.             echo ${state%%\]*}
  31.     fi
  32. }
  33.  
  34. # Имя текущего подключения (имя Wi-Fi либо Ethernet)
  35. fnet(){
  36.         nmout=$(nmcli -t -f NAME,TYPE con show --active)
  37.         conn=$( echo "$nmout" | grep ethernet)
  38.         if [[ "$conn" != "" ]]; then
  39.                 act_conn="Eth"
  40.         else
  41.                 conn=$( echo "$nmout" | grep wireless)
  42.                 if [[ "$conn" != "" ]]; then
  43.                         act_conn="${conn%:*}"
  44.                 else
  45.                         act_conn="No conn"
  46.                 fi
  47.         fi
  48.         echo $act_conn
  49. }
  50.  
  51. # генерируем строку для статусбара и украшаем ее с помощью эмодзи
  52. generate_content(){
  53.         echo "📶$(fnet)|🔈$(volume)|$(layout)|$(fdate)"
  54. }
  55.  
  56. # Выводим и обновляем статусбар раз в минуту
  57. while true; do
  58.     xsetroot -name "$(generate_content)"
  59.     sleep 1m
  60. done
Полная версия скрипта с батареей и подсветкой выложена тут и доступна по подписке.
Даем скрипту права на исполнение (chmod +x bar.sh) и кидаем его в автозапуск в .xprofile
  1. bar.sh &

И тут вы спросите - но если я переключаю раскладку/изменяю громкость, то данные в статусбаре не изменятся сразу! Верно. Статусбар обновляется, когда процесс sleep внутри цикла while завершится. А если sleep получит SIGTERM, то он тоже завершится! Это мы и будем использовать для обновления статусбара.
Представляю вам refbar.sh
  1. #!/usr/bin/bash
  2.  
  3. # look for sleep running inside bar.sh and kill it
  4. pid=$(pstree -lp | grep -- -bar.sh)
  5. pid=${pid##*bar.sh\(*sleep\(}
  6. pid=${pid%\)}
  7. kill $pid
Этот скрипт нужно вызывать из sxhkd при комбинациях, изменяющих данные в статусбаре:
  1. super + space
  2.     refbar.sh
  3.  
  4. XF86AudioRaiseVolume
  5.     amixer -D pulse sset Master 5%+ unmute; refbar.sh
  6.  
  7. XF86MonBrightnessDown
  8.     xbacklight -dec 10; refbar.sh

А теперь информация для тех кто использует Display Manager. SDDM, LightDM, и еще некоторые DM не прибивают все процессы пользователя при закрытии сессии, таким образом, если вы перезайдете несколько раз, то у вас будет несколько процессов bar.sh. К счастью, это фиксится путем прибивания процесса bar.sh перед запуском нового процесса bar.sh.
killbar.sh:
  1. #!/usr/bin/bash
  2.  
  3. # look for running bar.sh and kill it
  4. pid=$(pstree -lp | grep -- -bar.sh)
  5. pid=${pid##*bar.sh\(}
  6. pid=${pid%%\)*}
  7. kill $pid
.xprofile:
  1. killbar.sh
  2. bar.sh &

ПатчиЕсли на данном этапе вам не хватает какого-то функционала DWM, его можно дополнить патчами вот отсюда. Чтобы установить патч, скачивайте патч под вашу версию DWM, и применяйте его командой
  1. patch < patchname.diff
Советую перед тем, как патчить, выполнить вот эти команды:
  1. cp config.h config.def.h
  2. mv config.h config.h.bak
Т.к. в основном патчи применяются к config.def.h. Некоторые патчи кривые, и после их применения нужно будет покопаться в коде. Я сижу на ванильном DWM, но приведу вам некоторые патчи, которые могут быть интересны:
Autostart - автостарт скриптов из ~/.dwm. Полезно если вы используете dwm+dbus
Fullgaps - добавляет промежутки между окнами и позволяет регулировать их хоткеями
Swallow - при открытии графического приложения из терминала, скрывает терминал (и возвращает его после закрытия приложения)
Systray - полноценный трей. Туда можно засунуть nm-applet, там будут значки телеги, стима, дискорда и все такое
Xresources - добавляет возможность конфигурировать DWM с помощью ~/.Xresources
  • +5
  • views 1049