FreeBSD
January 20, 2020

Ricing your *nix desktop | Window managers

Window managers allow you control where to place frames (or windows) and how they look in a graphical user interface. The two main classes of window managers are tiling window managers and floating window managers.

Since everyone has different preferences and workflows, choosing a window manager should be a personal decision made uppon your needs.
  • Tiling window managers display layouts in non-overlapping frames named tiles. Those layouts cane be predefined but they can be defined and modified manually.
  • Floating window managers display frames in the "traditional desktop idea" used in commercial operating systems like Windows and OS X. Frames act like pieces of paper on a desk, and can be stacked on top of each other.

In the case of this guide, bspwm is a tiling window manager with options to make floating frames that don't stack in the tiling layout.

bspwm config by u/termwiz @ github

Right now if we don't have any desktop environment or window manager installed, after a clean installation we should be looking at the tty (the computer terminal). In order to reach our desktop we need to install a display server, named xorg.

In most cases your system is going to have xorg in their resources, so you should be able to install by just typing:

# install_command xorg

Where "install_command" is the one your system has. ( pkg install for freeBSD, apt-get install for Debian based, etc.)

For extra functionality, you can install the following packages if your system's xorg main package doesn't have them included:

xloadimage xsetroot xrdb

In our $HOME directory we need to create two dotfiles to configure the x system. The first one is .xinitrc and the second one is .Xresources.

$ touch .xinitrc
$ touch .Xresources

The .xinitrc file launches the desktop. It's a simple script called by the startx command.

Here's a basic .xinitrc file structure:

#!/bin/sh
# ~/.xinitrc

# load .Xresources

# set background wallpaper (if wanted)

# set default cursor

# start the simple X hotkey daemon

# launch status bar

# launch a terminal by default

# spawn window manager

Let's edit the file (from the tty you can run vi. vim, nano(if in linux) or ee(if in BSD)).

Note that your .xinitrc file will be empty without the comments.
#!/bin/sh
# ~/.xinitrc

# load .Xresources
xrdb -merge ~/.Xresources

# set background wallpaper (if wanted)
xsetbg -fullscreen /path/to/your/wallpaper.png &

# set default cursor
xsetroot -cursor_name left_ptr &

# start the simple X hotkey daemon
sxhkd &

# launch status bar

# launch a terminal by default

# spawn window manager
exec bspwm

We didn't fill all the comments in the file, but we'll come to those later.

Right now we cannot launch our desktop yet since the packages for the hotkey daemon and the window manager aren't installed. Most of the *nix derivations have bspwm into their packages' repo so you should be able to install by just typing:

# install_command bspwm

It requires some dependencies to work, specially note sxhkd. Your package manager should take care of the dependencies. If you opt to install bspwm from source you can look into the Makefile for the needed libs, or look into the make log if installation stops during the proccess.

bspwm relies in sxhkd to handle keyboard and pointer inputs.

After the installation, we need to create two sub-directories in our .config directory; one for bspwm and another one for sxhkd.

$ mkdir -p .config/{bspwm,sxhkd}

Inside .config/bspwm we need to create the configuration file for bspwm which is an executable shell script named bspwmrc.

$ touch .config/bspwm/bspwmrc

# chmod +x .config/bspwm/bspwmrc

Here's a basic bspwmrc file structure:

#!/bin/sh

# --monitors--
bspc monitor -d I II III IV

# --window managment--
bspc config border_width                0
bspc config window_gap                  4
bspc config split_ratio                 0.50

bspc config single_monocle              false
bspc config borderless_monocle          true
bspc config gapless_monocle             false
bspc config paddingless_monocle         false

bspc config focus_follows_pointer       true
bspc config pointer_follows_monitor     true
bspc config pointer_modifier            mod1
bspc config pointer_action1             move
bspc config pointer_action2             resize_side
bspc config click_to_focus              any
bspc config swallow_first_click         false
bspc config initial_polarity            first_child
bspc config ignore_ewmh_focus           true


# --rules--
bspc rule -a Firefox desktop='^2' follow=on focus=on

This will give some "default" configuration for the window manager.

  • Monitors' section allows you to define how many workspaces you want. The example has 4 monitors but you can extend them.
  • Window managment's section contains several config variables. Most of them are self-explanatory but you can learn more about the config variables in the bspwm documentation here.
  • Rule's section is also self-explanatory but syntax description is available here.

I encourage you to tweak it to fit your needs and workflows.

bspwm config by u/LukasDrsman @ r/unixporn

The same way we need a configuration file for sxhkd. Inside .config/sxhkd create a file named sxhkdrc.

$ touch .config/sxhkd/sxhkdrc

Here's an example file for sxhkd:

The super key by default refers to the key launcher from your keyboard, usually the one with the Windows or MacOs logo.
#   
# wm independent hotkeys   
#   
 
# terminal emulator   
super + Return    
    #terminal_name    
   
# program launcher   
super + @space    
    #program_launchers_name    
   
# make sxhkd reload its configuration files:   
super + Escape    
    pkill -USR1 -x sxhkd    

#   
# bspwm hotkeys   
#    

# quit/restart bspwm   
super + alt + {q,r}    
    bspc {quit,wm -r}    
   
# close and kill   
super + {_,shift + }w    
    bspc node -{c,k}   

#   
# state/flags   
#   
 
# set the window state   
super + {t,shift + t,s,f}    
    bspc node -t {tiled,pseudo_tiled,floating,fullscreen}    
   
# set the node flags   
super + ctrl + {m,x,y,z}    
    bspc node -g {marked,locked,sticky,private}    
   
#   
# focus/swap   
#   
 
# focus the node in the given direction   
super + {_,shift + }{h,j,k,l}    
    bspc node -{f,s} {west,south,north,east}    

# focus the node for the given path jump   
super + {p,b,comma,period}    
    bspc node -f @{parent,brother,first,second}  
  
# focus the next/previous node in the current desktop   
super + {_,shift + }c    
    bspc node -f {next,prev}.local 
   
# focus the next/previous desktop in the current monitor   
super + bracket{left,right}    
    bspc desktop -f {prev,next}.local  
  
# focus the last node/desktop   
super + {grave,Tab}    
    bspc {node,desktop} -f last    

# focus the older or newer node in the focus history   
super + {o,i}    
    bspc wm -h off; \    
    bspc node {older,newer} -f; \    
    bspc wm -h on   
 
# focus or send to the given desktop   
super + {_,shift + }{1-9,0}    
    bspc {desktop -f,node -d} '^{1-9,10}'    

#   
# preselect   
# 
   
# preselect the direction   
super + ctrl + {h,j,k,l}    
    bspc node -p {west,south,north,east}   
 
# preselect the ratio   
super + ctrl + {1-9}    
    bspc node -o 0.{1-9}   
 
# cancel the preselection for the focused node   
super + ctrl + space    
    bspc node -p cancel    

# cancel the preselection for the focused desktop   
super + ctrl + shift + space    
    bspc query -N -d | xargs -I id -n 1 bspc node id -p cancel    
   
#   
# move/resize   
# 
   
# expand a window by moving one of its side outward   
super + alt + {h,j,k,l}    
    bspc node -z {left -20 0,bottom 0 20,top 0 -20,right 20 0}   
 
# contract a window by moving one of its side inward   
super + alt + shift + {h,j,k,l}    
    bspc node -z {right -20 0,top 0 20,bottom 0 -20,left 20 0} 
   
# move a floating window 
super + {Left,Down,Up,Right}
    bspc node -v {-20 0,0 20,0 -20,20 0}

It's quite long but in the end we're configuring the desktop as our wish. Note that the first key combinations (the ones for launching the terminal and the program launcher) have comments in the action space. We'll add our program names once we install them.

Following the syntax scheme you can add your own key combination to launch the program you want.