Bspwm/Sxhkd connoisseurs/newbies

Hello there,
After searching the forum to see what’s already in about Bspwm/Sxhkd I must say that there is just few things here & there but as the archlabs-installer provides it I’d like to bring more material to the Communauty. First there’s a very good youtube playlist about Bspwm, owned by a Debian user who brings also very good scripts related to our subject.
Bspwm seems limited, obscure the first time you launch it, but it’s a lure because after all bspwmrc is just a shell script, so we can with a little persistence, order it to do things the way we want … at least if you take time to read the man-pages. This guy is full of options and the syntax is clear.
So first I post my bspwmrc file witch looks bloated if we compare it with the default one.
Some usefull tools to have: xdo xdotool xtitle xorg-xprop.
I will discuss the different sections over time.

#!/bin/bash

#### BSPWM CONFIGURATION FILE ####

_main() {

    #### MONITORS & DESKTOP SETTINGS ####
    # In case you want to swap monitors: bspc monitor DP-0 -s HDMI-0
    # $MONITOR{1,2,3} are environment variables.

    if [[ -n $(pidof nvidia-persistenced) ]]; then
        bspc monitor $MONITOR1 -d 1 2 3 4
        bspc monitor $MONITOR2 -d 5 6 7
        bspc monitor $MONITOR3 -d 8 9 10
    else
        bspc monitor DP-1 -d 1 2 3 4
        bspc monitor HDMI-1 -d 5 6 7
        bspc monitor DVI-D-1 -d 8 9 10
    fi

    # External scripts.
    _check sxhkd-start && sxhkd-start &
    _check bspwm_xdo_polybar && bspwm_xdo_polybar
    _check bspwm_external_rules && \
        bspc config external_rules_command \
            "$(command -v bspwm_external_rules)"

    #### DESKTOP LAYOUTS (tiled is the default) ####

    bspc desktop 1 -l monocle

    bsp-layout set wide 8
    bsp-layout set rtall 9 --master-size 0.52
    bsp-layout set even 10

    #### BSPC CONFIG CALLS ####

    for opts in "automatic_scheme alternate" \
                "border_width 1" \
                "borderless_monocle true" \
                "bottom_padding 0" \
                "click_to_focus button1" \
                "center_pseudo_tiled true" \
                "focus_follows_pointer true" \
                "gapless_monocle true" \
                "ignore_ewmh_focus false" \
                "left_padding 0" \
                "pointer_modifier mod4" \
                "pointer_follows_monitor true" \
                "pointer_follows_focus true" \
                "pointer_action1 move" \
                "pointer_action2 resize_side" \
                "pointer_action3 resize_corner" \
                "presel_feedback true" \
                "right_padding 0" \
                "single_monocle false" \
                "split_ratio 0.52" \
                "top_padding 25" \
                "window_gap 5"
    do
        # we want term splitting, so we don't quote here.
        # shellcheck disable=SC2086

        set -- $opts
        bspc config "$@"
    done

    #### BSPC CONFIG COLORS (see _getcolors function) ####
    # RESOURCES_FILE is an environment variable

    [[ -f $RESOURCES_FILE ]] && _getcolors

    #### BSPWM SPECIFIC CURSOR SHAPE ####

    xsetroot -cursor_name left_ptr

    #### APPS RULES & ASSIGNMENTS ####
    # If refreshing bspwmrc, remove all previous rules
    # to prevent doubling up.
    # bspc rule -r "*"

    declare -a floating=( "Alacritty" "Confirm" "Five-or-more" "G213colors-gui" \
                        "mpv" "Nitrogen" "Nm-connection-editor" \
                        "Pavucontrol" "Pulseaudio-equalizer-gtk" \
                        "qt5ct" "Sol" "URxvt:pulsemixer" )

    for i in "${floating[@]}"; do
        _rules "$i" state=floating focus=on center=on
    done

    declare -a systemui=( "Lxappearance" "Fpm2" "Gnome-disks" \
                        "Gufw.py" "GParted" "URxvt:search_install" )

    for i in "${systemui[@]}"; do
        _rules "$i" desktop=^3 follow=on state=floating center=on
    done

    # Monitor 1
    _rules firefox              desktop=^1 follow=on
    _rules URxvt:mpv-menu       desktop=^1 follow=on
    _rules Geany                desktop=^1 follow=on
    _rules Pcmanfm              desktop=^2 follow=on
    _rules File-roller          desktop=^2 follow=on
    _rules Filezilla            desktop=^2 follow=on
    _rules feh                  desktop=^4 follow=on state=fullscreen
    _rules Nitrogen             desktop=^4 follow=on
    _rules Zathura              desktop=^4 follow=on state=tiled
    _rules SimpleScreenRecorder desktop=^4 follow=on
    _rules qv4l2                desktop=^4 follow=on
    _rules Mumble               desktop=^4 follow=on state=floating

    # Monitor 2
    _rules lite                 desktop=^5 follow=on
    _rules mpv                  desktop=^6 follow=on
    _rules URxvt:youtube        desktop=^6 follow=on
    _rules VirtualBox           desktop=^6 follow=on
    _rules qvidcap              desktop=^6 follow=on
    _rules Five-or-more         desktop=^7 follow=on state=floating
    _rules Sol                  desktop=^7 follow=on state=floating

    # Monitor 3
    _rules URxvt:ncmpcpp        desktop=^8 follow=on
    _rules URxvt:pulsemixer     desktop=^8 follow=on
    _rules URxvt:cmus           desktop=^8 follow=on
    _rules URxvt:ripper         desktop=^8 follow=on
    _rules URxvt:htop           desktop=^9 follow=on
    _rules URxvt:jnettop        desktop=^9 follow=on
    _rules URxvt:newsboat       desktop=^10 follow=on
    _rules URxvt:mutt           desktop=^10 follow=on
    _rules URxvt:packagelist    desktop=^10 follow=on
    _rules XTerm                desktop=^10 follow=on

}

_check() { command -v "$1" >/dev/null; }

_getcolors() {

    local red blu mag cyn

    red="$(xrdb -query | awk '/color1:/{print $NF}')"
    blu="$(xrdb -query | awk '/color4:/{print $NF}')"
    mag="$(xrdb -query | awk '/color5:/{print $NF}')"
    cyn="$(xrdb -query | awk '/color6:/{print $NF}')"

    bspc config active_border_color   "$blu"
    bspc config focused_border_color  "$cyn"
    bspc config normal_border_color   "$mag"
    bspc config presel_feedback_color "$red"

}

_rules() { bspc rule -a "$@"; }

_main "${@}"

bspc desktop -f ^1

Sxhkd is also provided by the same developer and we can talk about it later if you wish.
Thanks for sharing your files here. :slightly_smiling_face:

Now let 's take a look at some sections:

  • Monitors.

bspc monitor HDMI-1 -d 1 2 3 4 5
bspc monitor DVI-D-1 -d 6 7 8 9 10

We have to define our monitors’ names by using the xrandr command, and the workspaces definition (-d) or desktops. Name can be whatever you want as long as you also list them in your bar config if you use one.

  • Desktop layouts.

bspc desktop 1 -l monocle
bspc desktop 2 -l monocle
bspc desktop 3 -l monocle
bspc desktop 5 -l monocle

Here I want desktops 1, 2, 3 & 5 to use the (-l) layout called ‘monocle’ as default. There is two of them, the other one is ‘tiled’.

  • bspc config

_bc() {
bspc config “$@”
}

This part is where we define general window configuration, easy to read. Again, if you look at the man-pages there is more to enable or disable.

  • bspc rules

_br() {
bspc rule -a “$@”
}

Here you place window rules, for example the size, placement and state. If you want specific assignment for applications on certain desktops.
You can also add more “complex” section for example small windows like: lxappearance, pavucontrol etc…

declare -a float=(Nm-connection-editor Pavucontrol \
qt5ct Confirm URxvt:scratchpad)

for i in ${float[@]}; do
   bspc rule -a $i state=floating follow=on focus=on; done 

But it is also possible to tell bspwm to take into account external rules refering to scripts, this way you can add MORE COMPLEX parts, that is the beauty of it.

_check() {
	command -v "$1" > /dev/null
}

_check bspwm_external_rules && \
    _bc external_rules_command \
        "$(command -v bspwm_external_rules)"

And finaly you can invoke commands (xdo) to manage things like polybar.

# polybar hidden when video applications get fullscreen.

xdo below -t $(xdo id -n root) $(xdo id -a polybar-bspwm-1-bar_HDMI-1)
xdo below -t $(xdo id -n root) $(xdo id -a polybar-bspwm-2-bar_DVI-D-1)

Now let’s talk about Sxhkd, the Simple X Hot Keys Daemon. Witch can be used as an applications launcher with some other window managers, this way we can keep common keybindings.
This tool also looks pretty straight simple and because of this, it is very extensible. For example I have divided its config in two files. The first one is dedicated to launch applications (sxhkdrc) and the second one is for window management (sxhkdrc_bspc). So I do:

sxhkd -c “$HOME”/.config/sxhkd/sxhkdrc{,_bspc} &

There are several ways to launch applications, eg:

super + f
   pcmanfm
super + ctrl + f
   firefox

But we should combine so as not to run out of key if we want to configure a lot of launchers.

super + {_, ctrl + } f
    {pcmanfm, firefox}

Another way is to chain with the semicolon sign. This tell sxhkd to listen our next pressed key, eg:

# URxvt applications
super + u ; {c,h,m,n,p,y}
	{ \
	urxvtc -name cmus -e cmus, \
	urxvtc -name htop -e htop -u archangel, \
	urxvtc -name ncmpcpp -e ncmpcpp -S clock --quiet, \
	urxvtc -name newsboat -e newsboat, \
	urxvtc -name ncpamixer -e ncpamixer, \
	urxvtc -name mpsyt -e mpsyt \
	}

So super + u , release the keys and then c for cmus, h for htop etc…
I also could use the colon signe [:] so sxhkd listens continuously until the Escape key is pressed, this way I launch apps one after the other with only one letter c, h, m, n etc…

All right guys, I hope some of you have been interested. :unamused: :sweat_smile:
As I said higher I will edit this post again with new features.
Feel free to correct me.
Related post bsp-layout-more-layouts-for-bspwm

4 Likes

Top, thx for sharing @archus

hey altman how are you my dear, nice to see you here :smiley:

Not that bad on my end, nice to see you also !

Nice. I see a couple rules in there I may add.
Thanks for sharing.

Nice thread. I’ve only ever used bspwm in it’s basic form. Some nice ideas presented here.

@archus thanks for this information. It would be really good to see this expanded even further with more tricks from other users etc.