software March 13, 2015 Jack 6 comments

On Bspwm Tweaking

I’ve written before on my travels through the tiling WM landscape. It’s been awhile though.

My most recent discovery is bspwm, which is a tiling WM that mixes automatic (think Xmonad) and manual (think ion3/notion) tiling as well as a hands off, but play nice approach to other desktop necessities like status bars and trays.

Why bspwm?

  • It’s Minimal. Similar to Xmonad, bspwm does exactly one thing, but does it extremely well. It places windows. It doesn’t have a built-in anything. No trays. No status bars. No menus. It doesn’t even directly handle keybinds thanks to a companion program by the same author (Bastien Dejean) call sxhkd or Simple X HotKey Daemon which is a flexible tool to map keybinds to simple command execution similar to xbindkeys but better. In my experience, built-in extra-features of WMs are often lacking the amount of flexibility I want, so no loss there.
  • It’s Scriptable. Bspwm has a companion program, bspc that can be used from the command line, or a script, to accomplish any action bspwm is capable of. In fact, bspc‘s so complete that all of the default sxhkd binds are bspc commands and the bspwmrc is nothing but a shell script calling bspc to set configuration options, along with whatever other startup stuff you wish.
  • It Communicates. It’s a simple affair to extract information from bspwm, both via bspc and via the status FIFO that can be used to receive notification of bspwm internal events.

To summarize, bspwm fits into the sweet spot where it has the minimalism of Xmonad, trading out the Haskell for shell scripts and a whole lot of scripting potential.

My Setup

First an obligatory double-wide screenshot.


Very simple, but there are a few upgrades from the examples in the git repo, despite the fact that the color scheme is the same.

  • Easy Named Desktops. I’ve written a couple of helper scripts around bspc and dmenu that make it simple to create, switch to, rename, or destroy named desktops.
  • Enumerated Desktops. They’re also numbered along so that bspwm’s default keybinds are more easily used along with their descriptive names.
  • Double Monitor Status Bar. I’ve split the monitor/desktop output of the status bar so that each monitor’s information is displayed on it, rather than all on the left side of the bar.

  • Keybinds for Focusing/Sending to Monitors. A simple job for bspc, I was surprised there was no default bind for it, but these binds allow you to shift windows and focus from one screen to another without knowing which desktop is on which.
  • Battery Monitor. I added a simple battery monitor on my laptop host.
  • A Tray. I’ve configured stalonetray to blend into my status bar.
  • Simplified Files. I much preferred having the panel configuration all in one file, instead of three (or four, if you count tweaking your .profile).
  • Hostname Tweaks. Tweaks to make my single config work identically between my desktop and laptop.

Named Desktops

Bspwm natively supports named desktops, but they’re cumbersome to use since you have to use bspc from somewhere. The example config spawns 10 desktops by number and calls it good. Well, coming from notion (a fork of ion3), I got used to the ability to name desktops something useful to remember what the hell I was doing on them, and then shift between them easily.

As such, I’ve added two scripts, which are trivial wrappers around dmenu and bspc

I put these into my $PATH someplace, I use ~/bin for all of my custom scripts.

Then, in sxhkdrc:

This allows you to use Super + d to create a new named desktop, or switch to it if it already exists. Super + ctrl + d will rename the currently focused desktop. Finally, Super + alt + d will destroy the focused desktop (but only if it’s empty and not the only desktop on its monitor, which is a restriction of bspwm).

Panel Improvements

I’ve combined the various panel example files into a custom single file that’s still run from bspwmrc.

This covers the enumerated desktops, split monitor status, tray, and hostname tweaks I mentioned above.

Here’s the full panel script, commented with improvements:

I can’t really explain any better than the comments, but I think I’m using a decent setup that will allow for future additions to the panel pretty easily just by mimicking the date and battery status functions and their invocations.

Monitor Binds

I simply added this to my sxhkdrc

This follows the Xmonad convention, where Q and W represent left and right monitors respectively, so super + q focuses the left monitor, super + w the right monitor. If I had three monitors, I would use QWE for Left, Center, Right.

The second set of binds sets up super + shift + q/w to send windows to a specific monitor’s desktop, and super + alt + q/w to shift an entire desktop to another monitor. I find bspwm’s desktop focus to be a bit wonky with multiple monitors (focusing a desktop will focus it on whatever monitor it’s associated with, rather than the current monitor), but I still only rarely have to shift desktops between monitors.

In order for these binds to work correctly on multiple hosts, in bspwmrc I added this block to rename my monitors consistently across machines.

This also clears the desktops, down to a single unnamed desktop on each monitor.


You can grab my config files here.

This includes everything you should need to run bspwm with my config. It untars such that the bspwm-config directory is like your HOME, so the config files are in .config, and won’t be visible by default.

The only caveat is that you’ll need to put the bin files in your $PATH someplace. Like the example config, it also expects that you have xtitle and bar-ain't-recursive installed.

If I end up making any more significant changes, I’ll consider putting this up on my Github, but for now I’m pretty content with my setup and don’t feel the need to version control it.

6 thoughts on “On Bspwm Tweaking

  1. Thanks for the great write-up! Not sure why, but for me the behavior of [panel_bar | bar] with [read line < $PANEL_FIFO] (like in your script) is a bit different from the bspwm panel example, which instead has [cat "$PANEL_FIFO" | panel_bar] with [read line -r] (from stdin). With your version, redirecting xtitle, clock, and bspc to the fifo frequently fails for some reason (maybe due to something I don't understand about redirection), causing only one to two of the desktop indicator, title, and clock to show up on any given run. I fixed it by making panel_bar a function like you did, but reading from stdin like the example, then catting the fifo to this function.

  2. I like the way you have got rid of some config files but you didn’t say if your desktop numbers in the bar are clickable? So you can click on them instead of always having to use the keyboard.

  3. Thank you for publishing this article. I having been using bspwm for a year and really love it. I am currently working on a new “ricing”. I really like your color scheme in the terminal shots. Would you be willing to provide their color scheme? They are great. So easy to read configs. I spend alot of time working on code and I find this color scheme great.

    1. Since you mentioned configs, I’m assuming you mean the syntax highlighting on the site and not the random Vim session in my screens.

      I’m using a plugin called “Crayon Syntax Highlighter” which comes with a theme “Son of Obsidian”, that has a page here: Unfortunately, it looks like a Visual Studio scheme by default =/

Leave a Reply

Your email address will not be published. Required fields are marked *