PálcikaWM VIII. : Bspwm

enlightened Ez az oldal a közösségért készül. heart Kövess minket máshol is:  Linux Mint Magyar Közösség a Mastodon-on  Telegram csatorna – csak hírek  Beszélgessünk a Telegram – Linux csevegő csoport  Hírek olvasása RSS segítségével  Linux Mint Hivatalos Magyar Közösség a Facebook-on      Linux Mint Baráti Kör a Facebook-on
wink Ha hasznosnak találod, és szeretnéd, hogy folytatódjon, támogasd a munkát Ko-fi vagy Paypal segítségével. laugh

Aki olvasgatja az írásaimat, az tudja, hogy megléptem, amit már rég tervezgetek, Linuxról BSD-re váltottam; ezért már most felhívnám a figyelmet, hogy a rendszer GhostBSD alatt lett tesztelve! A dzen2 panel konfigurációs szkriptje különösen épít BSD eszközökre, ennek bizonyos részeit csak útmutatóként tudod Linux alatt használni!

Tehát a mai témánk egy bspwm+ sxhkd+ dzen2 kombó bemutatása.

BSPWM!

A sztori központi eleme a bspwm, ami egy úgynevezett bináris fa struktúrát valósít meg (innen a neve: Binary Space Partitioning Window Manager). Gyakorlatilag minden alkalommal, amikor megnyitsz egy új ablakot, felosztja az aktuális munkaterületet (függőlegesen vagy vízszintesen), és az új ablakot az így kapott "levélbe" helyezi. Minden szülőelemnek (csomópontnak [internal node]) legfeljebb két gyermeke (levele [leaf]) lehet (bal és jobb ág).

Képernyő elrendezése:             Bináris fa struktúra:

+-------------------+-------------------+            Gyökér
|                   |         B         |           /    \
|                   |                   |          A     Vágás
|         A         +-------------------+                /   \
|                   |         C         |               B     C
|                   |                   |
+-------------------+-------------------+     

Miért jó ez?
Míg más csempéző ablakkezelők gyakran bonyolult szabályokat igényelnek, addig a bspwm a bináris fának köszönhetően automatikusan egyensúlyban tartja a képernyőterületet, így a legkevesebb kézi beavatkozással kapod a legoptimálisabb elrendezést.
Mivel az ablakok egy fában helyezkednek el, a parancssorból vagy billentyűkombinációkkal nemcsak az alapján navigálhatsz, hogy mi van „balra” vagy „jobbra” tőled, hanem a fa struktúráján belül is mozoghatsz (szülő [parent] és testvér [sibling]).
Azt is megmondhatod a rendszernek, hogy a következő ablakot hová nyissa meg a fában, ez igazán rugalmassá teszi a használatát!

A bspwm-nek nincs saját konfigurációs fájlja, helyette egy shell-szkriptből (bspwmrc), a bspc parancssori eszközzel tudjuk vezérelni. 
Nézzük az enyémet (~/.config/bspwm/bspwmrc):

#!/bin/sh
# ============================================================
#  Berus bspwmrc (GhostBSD)
# ============================================================
# Ezt a fájlt a bspwm a MUNKAMENET INDULÁSAKOR hajtja végre.
#
# HELY:    ~/.config/bspwm/bspwmrc
# FONTOS:  futtathatónak kell lennie:  chmod +x ~/.config/bspwm/bspwmrc
#
# MEGJEGYZÉS: a fájl /bin/sh-ban fut (BSD rendszerhéj), ezért
# itt NINCS bash-specifikus szintaxis (pl. kapcsos zárójel-listák).
# ============================================================

# ------------------------------------------------------------
# 1. DBus munkamenet-busz
# ------------------------------------------------------------
# A lightdm általában elindítja, de ha mégis hiányozna a
# környezeti változó (pl. kézi startX esetén), itt gondoskodunk róla.
if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then
    eval "$(dbus-launch --sh-syntax --exit-with-session)"
fi

# ------------------------------------------------------------
# 2. Sxhkd elindítása (a billentyűparancsok figyelője)
# ------------------------------------------------------------
# Az sxhkd olvassa a ~/.config/sxhkd/sxhkdrc fájlt és végrehajtja
# a parancsokat. Csak akkor indítjuk, ha még nem fut – így a bspwm
# újraindításakor (super + alt + r) nem indul kétszer.
if ! pgrep -x sxhkd >/dev/null 2>&1; then
    sxhkd &
fi

# ------------------------------------------------------------
# 3. Magyar billentyűzetkiosztás
# ------------------------------------------------------------
setxkbmap -model pc105 -layout hu

# ------------------------------------------------------------
# 4. Egérkurzor normalizálása
# ------------------------------------------------------------
# Az X alapértelmezett nagy "X"-es kurzora helyett normál nyíl.
xsetroot -cursor_name left_ptr

# ------------------------------------------------------------
# 5. Monitor(ok) és munkaterületek (desktopok)
# ------------------------------------------------------------
# A "bspc monitor -d …" felsorolja a monitor munkaterületeit.
# A munkaterületeket a super+1..9 billentyűkkel tudod váltani
# (lásd sxhkdrc), a dzen2 panel pedig mutatja és kattintható.
#
# Két monitor esetén például:
#   bspc monitor DP-1   -d 1 2 3 4 5
#   bspc monitor HDMI-1 -d 6 7 8 9
# A monitorneveket az "xrandr" paranccsal listázhatod ki.
bspc monitor -d 1 2 3 4 5 6 7 8 9

# ------------------------------------------------------------
# 6. Alapbeállítások
# ------------------------------------------------------------
# Minden sor egy-egy bspwm-tulajdonság.
bspc config border_width          2     # ablakkeret vastagsága (pixel)
bspc config window_gap            12    # hézag az ablakok között; super+b ideiglenesen kikapcsolja
bspc config split_ratio           0.52  # az új ablak aránya felosztáskor (0.50 = fele-fele)
bspc config borderless_monocle    true  # monocle módban ne legyen keret
bspc config gapless_monocle       true  # monocle módban hézag nélkül töltse ki
bspc config focus_follows_pointer true  # fókuszál az ablakra, ha az egér fölé kerül
bspc config click_to_focus        any   # bármelyik egérgombbal fókuszálható az ablak
bspc config pointer_modifier      mod4  # super + húzás: ablak mozgatása/átméretezése egérrel
bspc config pointer_action1       move           # bal egérgomb:  mozgatás
bspc config pointer_action2       resize_side    # középső gomb:  oldal húzása
bspc config pointer_action3       resize_corner  # jobb gomb:     sarok húzása

#============================================================
# 7. Dracula paletta
#============================================================
bspc config normal_border_color   "#44475a"
bspc config active_border_color   "#6272a4"
bspc config focused_border_color  "#bd93f9"
bspc config presel_feedback_color "#bd93f9"
bspc config urgent_border_color   "#ff5555"

# ------------------------------------------------------------
# 8. Ablakszabályok
# ------------------------------------------------------------
# A szabályok a program WM_CLASS-ja alapján illeszkednek.
# Egy ablak osztályát így tudod meg: indítsd el a programot,
# majd egy terminálban:  xprop WM_CLASS   (utána kattints az ablakra)
# bspc rule -a kitty        desktop=^1     # a terminál mindig az 1-es munkaterületre
bspc rule -a pavucontrol  state=floating # a hangkeverő lebegő kis ablak legyen
# További példák (vedd ki a kettőskeresztet, ha kellenek):
#bspc rule -a Firefox     desktop=^2
#bspc rule -a Gimp        state=floating
#bspc rule -a Screenkey   manage=off     # ne "kezelje" az ablakot (felvételhez)

# ------------------------------------------------------------
# 9. Háttérprogramok indítása
# ------------------------------------------------------------
# picom: compositor (áttetszőségért felel).
# Minden bspwm-újratöltéskor újraindítjuk, így a picom beállításai
# is azonnal életbe lépnek. A "-b" hatására háttérfolyamatként fut.
pkill -x picom 2>/dev/null
picom -b

# dunst: értesítés-megjelenítő. Ha már fut, NEM indítjuk újra,
# mert az értesítési előzményei elvesznének.
pgrep -x dunst >/dev/null 2>&1 || dunst &

# gammastep indítása
pkill -x gammastep 2>/dev/null
gammastep &

# Háttérkép: ha van ~/wallpapers mappa képekkel, minden belépéskor
# véletlenszerű képet tesz fel (--bg-fill: kitölti a képernyőt,
# átméretezve, középre igazítva)
# if [ -d "$HOME/wallpapers" ] && [ -n "$(ls "$HOME/wallpapers" 2>/dev/null)" ]; then
#     feh --randomize --bg-fill "$HOME/wallpapers"
# fi
"$HOME/.fehbg"

# Panel (dzen2): a herbstluftwm-ből átírt 3 sávos megoldás
# (munkaterületek | ablakcím | CPU/MEM/hang/dátum). A szkript maga
# gondoskodik róla, hogy ne induljon duplán, és hogy lefoglalja
# a helyet a képernyő tetején (top_padding). Leállítás:
#   pkill -f 'config/bspwm/panel.sh'
"$HOME/.config/bspwm/panel.sh" &

# ------------------------------------------------------------
# 10. Megjegyzések
# ------------------------------------------------------------
# A dzen2 panel nem "dokkoló", ezért tálca-ikonok
# számára nincs hely a rendszerben – ha ilyenek kellenének, érdemes
# teljes rendszersávra (pl. polybar) váltani.
#

Szokásomhoz híven megjegyzésekkel bőségesen elláttam, szerintem nem szorul különösebben magyarázatra...

SXHKD!

A bspwm szigorúan csak az ablakokat kezeli, így a billentyűzet kezeléséhez be kell vonnunk az sxhkd-t!
Laci barátom írt a démonkáról egy részletes ismertetőt, ezért nem is ragoznám túl a dolgot, tessék visszakeresni!
Tehát nézzük a konfigurációs fájlomat (~/.config/sxhkd/sxhkdrc):

# ============================================================
#  Berus sxhkdrc – billentyűparancsok (GhostBSD)
# ============================================================
# Az sxhkd figyeli a billentyűzetet. Az ablakkezelést a
# "bspc" nevű parancs végzi.
#
# HELY: ~/.config/sxhkd/sxhkdrc

# ------------------------------------------------------------
# 1) PROGRAMINDÍTÁS
# ------------------------------------------------------------
# Terminál (kitty) megnyitása
super + Return
    kitty

# Ugyanez ctrl + alt + t-vel is.
# Egy programhoz több kombináció is tartozhat: mindegyikhez
# külön blokk kell – az sxhkd mindkettőt külön-külön figyeli.
ctrl + alt + t
    kitty

# Alkalmazásindító: a telepített programok menüje, gépeléssel kereshető
super + d
    rofi -show drun

# Parancsfuttató: közvetlenül parancsnevet írhatsz be (mint egy "Futtatás")
super + shift + d
    rofi -show run

# Hangkeverő
super + v
    pavucontrol

# Új véletlenszerű háttérkép a ~/wallpapers mappából
# super + shift + w
#     feh --randomize --bg-fill "$HOME/wallpapers"

# ------------------------------------------------------------
# 2) ABLAKOK: FÓKUSZ ÉS MOZGATÁS
# ------------------------------------------------------------
# Fókusz áthelyezése a megadott IRÁNYBAN lévő ablakra
# (h = west/balra, j = South/lefelé, k = north/felfelé, l = east/jobbra)
super + {h,j,k,l}
    bspc node -f {west,south,north,east}

# Az aktuális ablak megcserélése az adott irányban lévő szomszéddal
super + shift + {h,j,k,l}
    bspc node -s {west,south,north,east}

# Vissza az ELŐZŐLEG fókuszált ablakra (két ablak közötti "pingpongozás")
super + Tab
    bspc node -f last

# A "previous" a last előtti ablakot jelöli
super + shift + Tab
    bspc node -f previous

# Aktív ablak bezárása
super + q
    bspc node -c

# ------------------------------------------------------------
# 3) ABLAKÁLLAPOTOK ÉS ELRENDEZÉS
# ------------------------------------------------------------
# Teljes képernyő (fullscreen) be/ki
super + f
    bspc node -t fullscreen

# Lebegő (floating) mód
super + s
    bspc node -t floating

# Normál (tiled) mód visszaállítása
super + t
    bspc node -t tiled

# Monocle elrendezés: az ablakok egymásra "halmozódnak", csak a fókuszált
# látszik; super+h/l lépked közöttük. Váltás vissza: ugyanez a gomb.
super + m
    bspc desktop -l next

# Hézag (gap) ideiglenes ki/be kapcsolása
super + b
    bspc config window_gap $(( $(bspc config window_gap) > 0 ? 0 : 12 ))

# ------------------------------------------------------------
# 4) ÁTMÉRETEZÉS ÉS FORGATÁS
# ------------------------------------------------------------
# Átméretezés az ablak SZÉLEIHEZ képest
super + alt + {h,j,k,l}
    bspc node -z {left -20 0,bottom 0 20,top 0 -20,right 20 0}

# Az aktuális ablak alatti OSZTÁS (faág) forgatása 90 fokkal
super + alt + {Left,Right}
    bspc node -R {270,90}

# ------------------------------------------------------------
# 5) HELY-ELŐKIJELÖLÉS (PRESELECT)
# ------------------------------------------------------------
# Megadhatod előre, HOL nyíljon meg a KÖVETKEZŐ ablak
super + ctrl + {h,j,k,l}
    bspc node -p {west,south,north,east}

# Előkijelölés törlése
super + ctrl + space
    bspc node -p cancel

# ------------------------------------------------------------
# 6) MUNKATERÜLETEK (DESKTOPOK)
# ------------------------------------------------------------
# Váltás az 1..9. munkaterületre / az aktív ablak áthelyezése oda.
super + {_,shift + }{1-9}
    bspc {desktop -f,node -s} ^{1-9}

# ------------------------------------------------------------
# 7) HANG (PAMIXER)
# ------------------------------------------------------------
# Hangerő fel – multimédia gomb
XF86AudioRaiseVolume
    pamixer -i 5

# Hangerő le – multimédia gomb
XF86AudioLowerVolume
    pamixer -d 5

# Némítás be/ki – multimédia gomb
XF86AudioMute
    pamixer -t

# NUMERIKUS BILLENTYŰZET: a +, - és * gombok is a hangerőt vezérlik:
super + KP_Add
    pamixer -i 5

super + KP_Subtract
    pamixer -d 5

super + KP_Multiply
    pamixer -t

# ------------------------------------------------------------
# 8) ÉRTESÍTÉSEK (DUNST)
# ------------------------------------------------------------
# Az utolsó, már eltűnt értesítés előhívása (ha lemaradtál valamiről)
super + n
    dunstctl history-pop

# Minden látható értesítés eltüntetése
super + shift + n
    dunstctl close-all

# ------------------------------------------------------------
# 9) KÉPERNYŐKÉP (SCROT)
# ------------------------------------------------------------
# A képek a ~/kepek mappába kerülnek, időbélyeggel ellátva
# (%Y%m%d_%H%M%S = év hónap nap_óra perc másodperc).
# A mkdir -p gondoskodik róla, hogy a mappa létezzen.

# Teljes képernyő
Print
    mkdir -p "$HOME/kepek" && scrot "$HOME/kepek/kepernyokep_%Y%m%d_%H%M%S.jpg"

# Csak az aktív ablak (-u)
alt + Print
    mkdir -p "$HOME/kepek" && scrot -u "$HOME/kepek/ablak_%Y%m%d_%H%M%S.jpg"

# Kijelölt terület (-s): az egérrel húzol egy téglalapot
super + Print
    mkdir -p "$HOME/kepek" && scrot -s "$HOME/kepek/kijeloles_%Y%m%d_%H%M%S.jpg"

# ------------------------------------------------------------
# 10) FÉNYERŐ
# ------------------------------------------------------------
# A FreeBSD "backlight" parancsa állítja a háttérvilágítást.
# A "command -v" ellenőrzi, hogy létezik-e a parancs – így asztali
# gépen nem keletkezik hibaüzenet. Ha nem kell, töröld ezeket a blokkokat.
# XF86MonBrightnessUp
#     command -v backlight >/dev/null 2>&1 && backlight increase 10

# XF86MonBrightnessDown
#     command -v backlight >/dev/null 2>&1 && backlight decrease 10

# ------------------------------------------------------------
# 11) RENDSZER: ÚJRAOLVASÁS, ÚJRAINDÍTÁS, KILÉPÉS
# ------------------------------------------------------------
# sxhkd újratöltése: a USR1 jelre újraolvassa ezt a fájlt.
# (Így a módosítások azonnal élnek, újraindítás nélkül.)
super + Escape
    pkill -USR1 -x sxhkd

# bspwm újraindítása: a bspwmrc újra lefut (a nyitott ablakok
# megmaradnak).
super + alt + r
    bspc wm -r

# Kilépés a bspwm-ből
super + shift + e
    bspc quit

# Power menü (saját szkript)
super + shift + p
    ~/.local/bin/rmenu

Azt hiszem ez sem szorul magyarázatra...

DZEN2!

A bspwm-et általában a polybarral szokták párosítani, de én az utóbbit nem igazán kedvelem, így lett dzen2... A hlwm kapcsán írtam, hogy kicsit nehezen barátkoztunk össze a dzen2-vel (ami amúgy baromi nehézkes, de cserébe azt és úgy csinálja, ahogy te szeretnéd) , de ha már sikerült összeütni egy működő konfigot, gondoltam a legegyszerűbb mégiscsak beekecsölni bspwm alá is...
Újra felhívnám a figyelmet, hogy a konfig BSD specifikus részeket tartalmaz (CPU, memória, stb.), Linux alatt változatlan formában nem tudod használni!
Nézzük (~/.config/bspwm/panel.sh):

#!/usr/bin/env bash

# ============================================================
#  Berus – bspwm panel – 3 sávos dzen2 verzió (GhostBSD)
# ============================================================
# A herbstluftwm-es panel bspwm-re átírt változata. 
# ============================================================

# ============================================================
# 1. ALAPBEÁLLÍTÁSOK 
# ============================================================

# Modern Xft font. 
FONT="xft:DejaVu Sans Mono:size=10"

#============================================================
# Dracula paletta
#============================================================
BG_COLOR="#282a36"
FG_COLOR="#f8f8f2"

TAG_ACT="#50fa7b"
TAG_OCC="#8be9fd"
TAG_MUT="#ff5555"

VOL_COLOR="#bd93f9"
DATE_COLOR="#bd93f9"

CPU_COLOR="#8be9fd"
MEM_COLOR="#ffb86c"
WARN_COLOR="#f1fa8c"     # közepes terhelés
CRIT_COLOR="#ff5555"        # magas terhelés

# Küszöbök (százalék) a színváltáshoz.
WARN_PERCENT=60
CRIT_PERCENT=85

# Memória: a ZFS ARC gyorsítótár a "wired" memóriába számít,
# ezért ZFS rendszeren (GhostBSD) a használt memória nagynak
# látszik. 1 = az ARC méretét levonjuk a használtból,
# 0 = nyers (active + wired + laundry) érték.
SUBTRACT_ARC=0

# Panel magassága.
PANEL_HEIGHT=24

# Belső margók (konstansok, NEM szövegszélesség-függők).
LEFT_MARGIN=15
RIGHT_MARGIN=15

# A három sáv szélessége a monitor szélességének arányában.
# A címközép csak akkor pontos, ha LEFT_PERCENT = RIGHT_PERCENT.
LEFT_PERCENT=30
CENTER_PERCENT=40

# A monitor sorszáma a HERBSTLUFTWM-es megszokás szerint (0 = első).
# Használat: ./panel.sh [0|1|...]
MON_NUM="${1:-0}"
# Ugyanez bspwm-szelektorral kifejezve ('^1' = első monitor):
MON_IDX=$((MON_NUM + 1))

# ------------------------------------------------------------
# 1/b. ELŐZŐ PÉLDÁNY LEÁLLÍTÁSA
# ------------------------------------------------------------
# Ha a panel már fut (pl. "bspc wm -r" után), a régi példányt
# leállítjuk, és megvárjuk, míg eltűnik.
for old_pid in $(pgrep -f 'config/bspwm/panel.sh' 2>/dev/null); do
    [ "$old_pid" = "$$" ] && continue
    kill "$old_pid" 2>/dev/null
    i=0
    while kill -0 "$old_pid" 2>/dev/null && [ "$i" -lt 20 ]; do
        sleep 0.1
        i=$((i + 1))
    done
    # 2 másodperc után sem állt le? -> durva leállítás
    if kill -0 "$old_pid" 2>/dev/null; then
        pkill -KILL -P "$old_pid" 2>/dev/null
        kill -KILL "$old_pid" 2>/dev/null
    fi
done

# ============================================================
# 2. MONITOR GEOMETRIA
# ============================================================
# herbstclient monitor_rect helyett: az xrandr kimenetéből vesszük
# az N. CSATLAKOZTATOTT monitor geometriáját ("SZÉLxMAGASSÁG+X+Y").
# A kihúzott ("disconnected") kimeneteknek nincs geometriájuk, ezért
# a mintaillesztés azokat automatikusan kihagyja.
# A kimenet sorrendje:  X Y SZÉLESSÉG MAGASSÁG
# (Ellenőrzés:  xrandr --query | grep connected )
read -r X Y W H <<< "$(xrandr --query 2>/dev/null | awk -v n="$MON_NUM" '
    /[0-9]+x[0-9]+\+[0-9]+\+[0-9]+/ {
        c++
        if (c == n + 1) {
            Match($0, /[0-9]+x[0-9]+\+[0-9]+\+[0-9]+/)
            split(substr($0, RSTART, RLENGTH), g, /[x+]/)
            print g[3], g[4], g[1], g[2]
        }
    }')"

if [ -z "$W" ] || [ "$W" -le 0 ]; then
    echo "Hiba: nem sikerült lekérni a monitor szélességét." >&2
    exit 1
fi

if [ -z "$H" ] || [ "$H" -le 0 ]; then
    echo "Hiba: nem sikerült lekérni a monitor magasságát." >&2
    exit 1
fi

# A bspwm monitor-azonosítója. Minden bspc hívásnál EZZEL hivatkozunk
# a monitorra, hogy sose a "véletlenül fókuszban lévő" monitorra hasson
# a parancs.
if ! bspc query -M >/dev/null 2>&1; then
    echo "Hiba: a bspwm nem fut – a bspc nem tudott csatlakozni hozzá." >&2
    echo "      A panelt bspwm munkamenetben kell indítani; a bspwmrc ezt" >&2
    echo "      automatikusan megteszi. Kézi teszthez jelentkezz be a" >&2
    echo "      bspwmbe, majd futtasd egy terminálból:" >&2
    echo "          ~/.config/bspwm/panel.sh" >&2
    exit 1
fi

MON_ID="$(bspc query -M -m "^${MON_IDX}" 2>/dev/null | head -n1)"

if [ -z "$MON_ID" ]; then
    echo "Hiba: a bspwm fut, de nincs '${MON_IDX}'. sorszámú monitora." >&2
    echo "      (A bspwm a monitorokat 1-től számolja: az első monitor az" >&2
    echo "      '^1'.) Az elérhető monitorok nevei így listázhatók ki:" >&2
    echo "          bspc query -M --names" >&2
    exit 1
fi

# ============================================================
# 3. A HÁROM SÁV GEOMETRIÁJA  (változatlan)
# ============================================================

LEFT_W=$((W * LEFT_PERCENT / 100))
CENTER_W=$((W * CENTER_PERCENT / 100))
RIGHT_W=$((W - LEFT_W - CENTER_W))

LEFT_X=$X
CENTER_X=$((X + LEFT_W))
RIGHT_X=$((X + LEFT_W + CENTER_W))

# ============================================================
# 4. PANEL HELYFOGLALÁSA
# ============================================================
bspc config -m "$MON_ID" top_padding "$PANEL_HEIGHT"

# ============================================================
# 5. FIFO-K ÉS A HÁROM DZEN2 PÉLDÁNY INDÍTÁSA 
# ============================================================

TMP_DIR="$(mktemp -d)"

FIFO_LEFT="${TMP_DIR}/panel-left-${MON_NUM}"
FIFO_CENTER="${TMP_DIR}/panel-center-${MON_NUM}"
FIFO_RIGHT="${TMP_DIR}/panel-right-${MON_NUM}"

mkfifo "$FIFO_LEFT" "$FIFO_CENTER" "$FIFO_RIGHT"

cleanup() {
    exec {FD_LEFT}>&- 2>/dev/null
    exec {FD_CENTER}>&- 2>/dev/null
    exec {FD_RIGHT}>&- 2>/dev/null
    kill "$DZEN_LEFT_PID" "$DZEN_CENTER_PID" "$DZEN_RIGHT_PID" 2>/dev/null
    # A (ticker | bspc subscribe | while) csővezeték leállítása:
    # a szkript közvetlen gyerekei kapnak TERM jelet. A legtávolabbi
    # óraciklus ("ticker") a következő sikertelen echo-nál magától
    # megáll, hiszen nincs már olvasója.
    pkill -TERM -P "$$" 2>/dev/null
    # Padding visszaállítása – mintha sosem lett volna panel.
    if [ -n "$MON_ID" ]; then
        bspc config -m "$MON_ID" top_padding 0 2>/dev/null
    fi
    rm -rf "$TMP_DIR" 2>/dev/null
}

# INT/TERM esetén simán lépjünk ki: az EXIT csapda ilyenkor is
# lefuttatja a cleanup()-t, így a takarítás pontosan egyszer fut.
trap cleanup EXIT
trap 'exit 0' INT TERM

dzen2 \
    -x "$LEFT_X" -y "$Y" -w "$LEFT_W" -h "$PANEL_HEIGHT" \
    -fn "$FONT" -bg "$BG_COLOR" -fg "$FG_COLOR" \
    -ta l \
    < "$FIFO_LEFT" &
DZEN_LEFT_PID=$!

dzen2 \
    -x "$CENTER_X" -y "$Y" -w "$CENTER_W" -h "$PANEL_HEIGHT" \
    -fn "$FONT" -bg "$BG_COLOR" -fg "$FG_COLOR" \
    -ta c \
    < "$FIFO_CENTER" &
DZEN_CENTER_PID=$!

dzen2 \
    -x "$RIGHT_X" -y "$Y" -w "$RIGHT_W" -h "$PANEL_HEIGHT" \
    -fn "$FONT" -bg "$BG_COLOR" -fg "$FG_COLOR" \
    -ta r \
    < "$FIFO_RIGHT" &
DZEN_RIGHT_PID=$!

# Az fd-ket egyszer nyitjuk meg, hogy a FIFO ne záruljon be
# minden echo után (elkerülve az ismételt blokkoló nyitást).
exec {FD_LEFT}>"$FIFO_LEFT"
exec {FD_CENTER}>"$FIFO_CENTER"
exec {FD_RIGHT}>"$FIFO_RIGHT"

# ============================================================
# 6. SEGÉDFÜGGVÉNYEK ÉS KEZDŐÉRTÉKEK  (GhostBSD sysctl)
# ============================================================

# Százalékos érték színezése a küszöbök alapján.
# Használat: pick_color <százalék> <alapszín>
pick_color() {
    if [ "$1" -ge "$CRIT_PERCENT" ]; then
        echo "$CRIT_COLOR"
    elif [ "$1" -ge "$WARN_PERCENT" ]; then
        echo "$WARN_COLOR"
    else
        echo "$2"
    fi
}

# Memória: ezek az értékek nem változnak futás közben.
MEM_TOTAL="$(sysctl -n hw.physmem 2>/dev/null)"
PAGE_SIZE="$(sysctl -n vm.stats.vm.v_page_size 2>/dev/null)"

# CPU: a kern.cp_time az összes mag összesített számlálója
# (user nice sys intr idle). A használatot két mérés
# különbségéből számoljuk, ezért kell az előző érték.
read -r PREV_U PREV_N PREV_S PREV_I PREV_IDLE <<< "$(sysctl -n kern.cp_time 2>/dev/null)"
PREV_TOTAL=$((PREV_U + PREV_N + PREV_S + PREV_I + PREV_IDLE))
CPU_PERC=0

# ============================================================
# 7. ESEMÉNYEK ÉS ÓRA
# ============================================================
(
    while true; do
        echo "tick" || break   # ha az olvasó meghalt, a ciklus is álljon le
        sleep 1
    done &

    bspc subscribe monitor desktop node_add node_remove node_swap \
        node_transfer node_focus node_activate desktop_activate desktop_focus

) | while read -r event args; do

    # ========================================================
    # 8. CPU HASZNÁLAT 
    # ========================================================
    # Csak a másodpercenkénti "tick" eseményen frissítjük,
    # hogy a bspwm események (asztalváltás stb.) ne torzítsák
    # a mérést túl rövid időközökkel.

    if [ "$event" = "tick" ]; then

        read -r CUR_U CUR_N CUR_S CUR_I CUR_IDLE <<< "$(sysctl -n kern.cp_time 2>/dev/null)"

        CUR_TOTAL=$((CUR_U + CUR_N + CUR_S + CUR_I + CUR_IDLE))

        D_TOTAL=$((CUR_TOTAL - PREV_TOTAL))
        D_IDLE=$((CUR_IDLE - PREV_IDLE))

        if [ "$D_TOTAL" -gt 0 ]; then
            CPU_PERC=$(( 100 * (D_TOTAL - D_IDLE) / D_TOTAL ))
        fi

        PREV_TOTAL=$CUR_TOTAL
        PREV_IDLE=$CUR_IDLE

    fi

    CPU_COL="$(pick_color "$CPU_PERC" "$CPU_COLOR")"
    CPU_OUT="^fg(${CPU_COL})CPU: ${CPU_PERC}%^fg()"

    # ========================================================
    # 9. MEMÓRIA HASZNÁLAT  (BSD/ZFS-specifikus)
    # ========================================================

    MEM_OUT="^fg(${TAG_MUT})MEM: N/A^fg()"

    if [ -n "$MEM_TOTAL" ] && [ -n "$PAGE_SIZE" ] && [ "$MEM_TOTAL" -gt 0 ]; then

        read -r PG_ACTIVE PG_WIRED PG_LAUNDRY <<< "$(
            sysctl -n \
                vm.stats.vm.v_active_count \
                vm.stats.vm.v_wire_count \
                vm.stats.vm.v_laundry_count 2>/dev/null |
            tr '\n' ' '
        )"

        MEM_USED=$(( (${PG_ACTIVE:-0} + ${PG_WIRED:-0} + ${PG_LAUNDRY:-0}) * PAGE_SIZE ))

        if [ "$SUBTRACT_ARC" = "1" ]; then
            ARC_SIZE="$(sysctl -n kstat.zfs.misc.arcstats.size 2>/dev/null)"
            if [ -n "$ARC_SIZE" ] && [ "$ARC_SIZE" -lt "$MEM_USED" ]; then
                MEM_USED=$((MEM_USED - ARC_SIZE))
            fi
        fi

        MEM_PERC=$(( 100 * MEM_USED / MEM_TOTAL ))

        # GiB, egy tizedessel (egész aritmetikával).
        MEM_USED_TENTHS=$(( MEM_USED * 10 / 1073741824 ))
        MEM_USED_GB="$((MEM_USED_TENTHS / 10)).$((MEM_USED_TENTHS % 10))"

        MEM_COL="$(pick_color "$MEM_PERC" "$MEM_COLOR")"
        MEM_OUT="^fg(${MEM_COL})MEM: ${MEM_USED_GB}G (${MEM_PERC}%)^fg()"

    fi

    # ========================================================
    # 10. HANGERŐ 
    # ========================================================

    VOL_PERC="$(
        pactl get-sink-volume @DEFAULT_SINK@ 2>/dev/null |
        awk '{print $5}' |
        head -n1
    )"

    VOL_MUTE="$(
        pactl get-sink-mute @DEFAULT_SINK@ 2>/dev/null |
        awk '{print $2}'
    )"

    if [ -z "$VOL_PERC" ]; then
        VOL_OUT="^fg(${TAG_MUT})VOL: N/A^fg()"
    elif [ "$VOL_MUTE" = "yes" ]; then
        VOL_OUT="^fg(${TAG_MUT})VOL: MUTE^fg()"
    else
        VOL_OUT="^fg(${VOL_COLOR})VOL: ${VOL_PERC}^fg()"
    fi

    # ========================================================
    # 11. DÁTUM ÉS IDŐ 
    # ========================================================

    DATE_TEXT="$(date '+%Y-%m-%d %H:%M')"
    DATE_OUT="^fg(${DATE_COLOR})${DATE_TEXT}^fg()"

    # ========================================================
    # 12. TAG-EK (MUNKATERÜLETEK)
    # ========================================================
  
    TAGS_OUT=""

    FOCUSED_DESK="$(bspc query -D -m "$MON_ID" -d .focused --names 2>/dev/null | head -n1)"
    if [ -z "$FOCUSED_DESK" ]; then
        # Tartalék: globálisan fókuszált munkaterület
        # (egy monitoros gépen ez mindig ugyanaz).
        FOCUSED_DESK="$(bspc query -D -d .focused --names 2>/dev/null | head -n1)"
    fi

    URGENT_DESK="$(bspc query -D -m "$MON_ID" -d .urgent --names 2>/dev/null | head -n1)"
    if [ -z "$URGENT_DESK" ]; then
        URGENT_DESK="$(bspc query -D -d .urgent --names 2>/dev/null | head -n1)"
    fi

    for tag in $(bspc query -D -m "$MON_ID" --names 2>/dev/null); do

        CLICK_START="^ca(1,bspc desktop -f ${tag})"
        CLICK_END="^ca()"

        if [ "$tag" = "$FOCUSED_DESK" ]; then
            # Fókuszban: sötétebb háttér + zöld (mint az eredeti '#' állapot)
            TAGS_OUT+="${CLICK_START}^bg(#313244)^fg(${TAG_ACT}) ${tag} ^fg()^bg()${CLICK_END} "
        elif [ "$tag" = "$URGENT_DESK" ]; then
            # Sürgős: piros – valahol riasztás vár (pl. kész lett egy feladat)
            TAGS_OUT+="${CLICK_START}^bg(#313244)^fg(${TAG_MUT}) ${tag} ^fg()^bg()${CLICK_END} "
        elif [ -n "$(bspc query -N -d "$tag" 2>/dev/null)" ]; then
            # Foglalt (van ablak rajta), nincs fókuszban: kék
            TAGS_OUT+="${CLICK_START}^fg(${TAG_OCC}) ${tag} ^fg()${CLICK_END} "
        else
            # Üres: halvány
            TAGS_OUT+="${CLICK_START}^fg(#45475a) ${tag} ^fg()${CLICK_END} "
        fi

    done

    # ========================================================
    # 13. ABLAKCÍM
    # ========================================================
    # Ha nincs fókuszált ablak (pl. üres munkaterület), a cím üres.

    WIN_ID="$(bspc query -N -n focused 2>/dev/null)"

    WIN_TITLE=""
    if [ -n "$WIN_ID" ]; then
        WIN_TITLE="$(xprop -id "$WIN_ID" WM_NAME 2>/dev/null |
            sed -e 's/^WM_NAME[^=]*= //' -e 's/^"\(.*\)"$/\1/')"
    fi

    # Maximális hossz karakterben – ésszerű felső korlát hosszú
    # ablakcímeknél (a dzen2 úgyis elvágja a sáv szélénél).
    if [ "${#WIN_TITLE}" -gt 80 ]; then
        WIN_TITLE="${WIN_TITLE:0:77}…"
    fi

    WIN_OUT="^fg(${FG_COLOR})${WIN_TITLE}^fg()"

    # ========================================================
    # 14. SZÖVEGEK ÖSSZEÁLLÍTÁSA
    # ========================================================

    LEFT_LINE="${TAGS_OUT}"
    CENTER_LINE="${WIN_OUT}"
    RIGHT_LINE="${CPU_OUT}  |  ${MEM_OUT}  |  ${VOL_OUT}  |  ${DATE_OUT}"

    # ========================================================
    # 15. KIÍRÁS A HÁROM SÁVBA 
    # ========================================================

    echo -e "$LEFT_LINE"   >&$FD_LEFT
    echo -e "$CENTER_LINE" >&$FD_CENTER
    echo -e "$RIGHT_LINE"  >&$FD_RIGHT

done

Rengeteg magyarázat van benne, ha belevágnál... Ha nem, számos példát találsz bspwm+ polybar kombóra…!

A végére egy kis összefoglaló a bspwm navigációs/kezelési lehetőségeiről (fontosabb bspc parancsok):

bspc node -f west   # Váltás balra lévő ablakra
bspc node -f east   # Váltás jobbra lévő ablakra
bspc node -f south  # Váltás lefelé lévő ablakra
bspc node -f north  # Váltás felfelé lévő ablakra

bspc node -f @parent  # Ugrás a szülőre
bspc node -f @sibling # Ugrás a testvérre

bspc node -s east   # Felcseréli az aktuális ablakot a jobbra lévővel

bspc node -n @parent  # Beilleszti az ablakot a szülő csomópont szintjére

bspc node -p south  # A következő ablak alulra fog nyílni
bspc node -p east   # A következő ablak jobbra fog nyílni
bspc node -p cancel # Kijelölés törlése

bspc node -t tiled      # Csempézett mód
bspc node -t floating   # Lebegő mód 
bspc node -t fullscreen # Teljes képernyős mód

bspc node -c            # Bezárja a kijelölt ablakot
bspc node -k            # Erőszakos bezárás 

A pálcikawm világ örök kérdése, melyiket válaszd...?! A bspwm+ sxhkd mellett szól a gyorsaság és alacsony erőforrás-igény, minimális RAM-ot és CPU-t használnak, így gyengébb hardveren is remekül futnak. 
Amiért én imádom, a teljes testreszabhatóság! Nincsenek előre beállított elemek, rád kényszerített megoldások, úgy építed fel az asztali környezeted, ahogy neked tetszik, szabadon variálhatod a komponenseket.
És végül de nem utolsósorban a rendszer rendkívül stabil és megbízható!

Laci sxhkd cikke: https://linuxmint.hu/hir/2025/03/sxhkd-a-billentyuparancs-kezelo-0

Berus

Hozzászólások

Hogy őszinte legyek, abban a

Értékelés: 

0
Még nincs értékelve

Hogy őszinte legyek, abban a kis időben ami még hátravan, már nem nagyon tervezek Linux-al foglalkozni...

Amúgy érdekes projektnek tűnik, de az egész Linux-ra van kihegyezve, már a chadwm fordításához is át kéne nézni a fájlokat (config.mk, stb.), ennyit azért nem ér a dolog...

A klasszikus dwm-et használtam régebben, de a foltozgatás/fordítgatás túl sok időt vett el, így elengedtem...