FAQ TUBE GAMES BLOG

Minimalism? On Xmenu and DWM.

Minimalism is something I hold quite dear. At least technologically speaking. However, like many other terms, minimalism has been abused on the internet for a very long time. Life gurus on youtube with a MacBookPro in an empty white room claim to be “minimalists” without truly grasping what that word really means.

But let’s not split hairs here. Technologically speaking there are very little modern, usable operating systems or interfaces which can truly claim to be minimal, what with the importance that whe have bestowed upon their design. Not to mention the need to make interfaces usable for non-techie people. Commercially all of these “bloat” factors make perfect sense, and today outside the industrial sector you will never find computing interaces which hold minimalism over easy of use.

The great thing about linux however, is that you truly have the power over your own system and can use it in whatever way that you want. Instead of subscribing to the window management philosophies instilled into you as a child via Microsoft or Apple, why not go wild and try something completely different?

This is where the wave of minimalist tiling window managers really took off. These software projects have been around for a long time, however they only recently became popular through a magic sprinkling of memes, originating from certain mongolian basket weaving forums.

Regardless of your opinion on the current, overhyped, reddit infused meme culture that surrounds minimal software and tiling window managers specifically, once you start using them and getting a configuration going, they are truly a joy both in speed, customizability and self sufficiency. Something we germans like to reffer to as “Narrenfreiheit

The god among men, when it comes to self sufficiency and elitism in X11 window managers is none other than DWM by the Suckless Team.

dwm

Long story short, in order to use any of the sucklles utilities, the user must edit the C source code and compile their own versions for usage. After spending a few months with not just DWM, but most of their tools, I am convinced that this could have become a much more popular avenue for software as a whole, had it come earlier and with more fanfare.

By forcing users to understand the code which they run, you limit yourself to a small subset of geeks. Most average users shriek at even the most simple error message on their screen. Expecting these people to not shit their pants when confronted with source code is sadly out of the question. But many would have taken the challenge, grown by facing it head on and left with a greater understanding of programming, compilation and the open source movement as a whole.

The usability of DWM comes into play, by combining it with other suckless utilities. ST is a truly minimal terminal emulator and SURF is a webkit based browser, which only displays one webpage, no further UI or funtionality included. While these sound like barren tools that have no business being as minimal as they are, their usefulness stems from suckless’ unique approach to feautre implementation, with TABBED being the best example. This tool allows ANY application to be tabbed. It usex XEmbed to create an X11 window with tabs at the top, allowing the user to navigate instances of ANY program!

Tabbed ST with classic memes

Want your file explorer to have tabs? Just open a tabbed instance of your file explorer! Same with browsers, text editors, you name it! If this were applied to more software, all common UI abstractions could be implemented system wide, instead of being reimplemented in every other program you use. This kind of approach to UI and its usage seems alien, even though in the unix world, such far-out approaches used to be common place. I mean just check out the funky UI and input methods of the Plan9 Operatings System from Belle Labs back in the day!

The best suckless utility to showcase this approach to user interace and interaction is by far DMENU. This menuing system, dubbed the “dynamic menu” is used on a variety of minimal linux envirionments and distributions. Notably “baby’s first tiling WM (i3)” uses it for its application launching. And this is what most users will recognize this little menu as: an application launcher. dmenu

One look at the man page however will reveal where this program gets its supposed name “dynamic menu” from. Using unix plumbing this menu unlocks its intended purpose and true potential. By feeding it a list of newline seperated itesms from a file or as the output of another command, it will bring up a menu containing all these items at the top or bottom of the screen. The user can then either use the arrow keys to select their desired entry or begin typing it to narrow down a larger list of items. By pressing enter, that entry string is selected and given to standard output. This means that one can string any number of commands and dmenus togehter, to create amazingly complex chains of functionality, using nothing but the shell. This gives users the power to create functionality with user input, without bringing up a terminal window and without using a bloated UI framework for simple tasks.

I personally use dmenu in what feels like most of my personal scripts and it has been one of my most beloved utilities for a few years now.

The problem with minimalism in general however is that focusing and obsessing too much over it will inevitably result in lost time and resources, someting that is not minimal in the slightest. And as fun as a bare bones, lean and mean interface is, even the most hardcore free software enjoyer will one day just want to lean back and use the mouse for a while, even if they have every key on their keyboard mapped 3 layers over.


This is where XMenu comes in!

This little utility was written by Phill Bush over on GitHub. It is a generic cursor controlled menu, which reads all of the contents from standard input, much like dmenu! This is relevant, especially considering the system wide UI approach commonly found in suckless and suckless-like utilities. While GTK, QT and a larger number of other UI standards and application frameworks impose their own rules and implementations of even simple things like cursor controlled menus, this tool allows for any application to use a quick and reliable cursor menu, just by issuing a shell commmand in the background.

XMenu demo

While this is fine for a simple selection menu, it doesn’t seem to hold a candle to the common desktop right-click menu found in many operating systems and desktop environments. Mainly the functionality of nesting menus and application launching seems to be missing at first glance, this however is very much possible through interpretation of tab characters!

Xmenu man page:

 NAME
        xmenu - menu utility for X

 SYNOPSIS
        xmenu [-irw] [-p position] [title]

 DESCRIPTION
        xmenu  is  a  menu  for  X, it reads a list of newline-separated items from
        stdin, shows a menu for the user to select one of the  items,  and  outputs
        the item selected to stdout.
 [...]
        That means that each item is composed by tabs, followed by an optional  im‐
        age  specification,  followed by tabs followed by a label, followed by more
        tabs, followed by an output, and ended by a newline.   Brackets  group  op‐
        tional elements.

              The  initial tabs indicate the menu hierarchy: items indented with a
              tab is shown in a submenu of the preceding item  not  indented.   An
              item without initial tabs is a top-level item.

This allows users to write simple text files, containing nothing but correctly indented constructs of icons, labels and program names to create a nested launcher for all kinds of applications. This also means, that instead of lettings some bloated system like XDG take care of the population of these items, the user has full control and will wonder at no point where these entries are coming from.

Multiple text files for different scenarios can also be created. For instance, I created the directory ~/.config/xmenu_presets in which I store all of these files. Then I wrote a simple shell wrapper for using them named xmenu_run, after the application launching script dmenu_run which is bundled with dmenu itself. This script is part of my personal scripts but is quite basic:

#!/bin/bash

# Source bash config
source $HOME/.bashrc

# Configuration directory
CFG_DIR=$HOME/.config/xmenu_presets

# Coonfiguration Filename
case "$1" in
        # Desktop
        "-d")   CFG_FLN="xmenu_desktop";  break ;;
        # Title Bar
        "-t")   CFG_FLN="xmenu_titlebar"; break ;;
        # Status Bar
        "-s")   CFG_FLN="xmenu_status";   break ;; # Use custom filename
        "*")    CFG_FLN="$1";             break ;;
esac

# Execute Xmenu
cat "$CFG_DIR/$CFG_FLN" | xmenu | bash &

Using this, any program system wide can execute any of the xmenu presets of the current user. This simple but powerful workflow can allow a user with just a little bit of bash / shell knowlege to create surprisingly efficient little menus for themselves, instead of relying on alot of more involved or bloated solutions.

Here is part of my desktop menu config and how it appears in usage:

[...]
 Documents
         Libre Office  libreoffice
         MuPDF mupdf
磊 Media
         News
                 Newsboat      $TERM -e newsboat
         Images
                 Create
                         Krita krita

                 View Images   $EX mViewImages -x
                 Krita krita
         Video
                 Create
                         Olive Editor  olive
                         Blender       blender

                 MPV   mpv
         Music
                 Create
                         Audacity      audacity
                         LMMMS lmms
                         OpenMPT       openmpt

                 NCMPCPP       $TERM -e ncmpcpp
                 DeadBeef      deadbeef
[...]
XMenu in use

Incorporating Xmenu into DWM.

So far so good, we have got our comfy minimal suckless DWM setup primed and ready. Now we also found some sweet programs like XMenu to make our environment more usable without bowing down to overarching bloatware! But … how do we call XMenu? Uh, sure we can do it from the terminal, but how do we launch a specific XMenu configuration by, for instance, right-clicking on our desktop?

This is the proverbial lock for the key of my previous ramblings about suckless software. While Phill Bush also created an accompanying program for XMenu named XClickRoot in order to achieve this, the nature of suckless software allows any active user to incorporate XMenu directly into their build, rather than relying on an additional program just to launch a simple menu!

First, let me explain the terminology at play here. XClickRoot reffers to the windowing structure of X11. Every window you see on your screen is just a child node of a parent window. This approach makes sense, as many programs have seperate windows, which should be dependent on the existence of one main window. Instead of making the desktop something else entirely, just think about the desktop as one larger window covering your entire screen, on which all other windows depend and are children of. Keeping with unix naming schemes, this window is of course named the root window. Other programs can attach their events to actions on a given window. XClickRoot simply attaches the launching of XMenu to a right-click action being performed on the root window, effectively implementing desktop right-clicking in a crude way.

It doesn’t take much consideration to realise that while this works, having a whole seperate program in memory, just to monitor a set of data which is already controlled by the window manager is superfluous. So how can we do this in DWM itself?

Like with any piece of suckless software, we begin by looking into the configuration header file, where most of the programs variable definitions, which lend themselves to user editing, are implemented. Below the commonly edited Keyboard shortcuts is a section labled as “button definitions”, which deals with the mapping of mouse-click actions on various X11 windows handled by DWM.

config.def.h

[...]
/* button definitions */
static Button buttons[] = {
        /* click            event mask    button        function        argument */
        { ClkLtSymbol,      0,            Button1,      setlayout,      {0} },
        { ClkLtSymbol,      0,            Button3,      setlayout,      {.v = &layouts[2]} },
        { ClkWinTitle,      0,            Button2,      zoom,           {0} },
        { ClkStatusText,    0,            Button2,      spawn,          {.v = termcmd } },
        { ClkClientWin,     MODKEY,       Button1,      movemouse,      {0} },
        { ClkClientWin,     MODKEY,       Button2,      togglefloating, {0} },
        { ClkClientWin,     MODKEY,       Button3,      resizemouse,    {0} },
        { ClkTagBar,        0,            Button1,      view,           {0} },
        { ClkTagBar,        0,            Button3,      toggleview,     {0} },
        { ClkTagBar,        MODKEY,       Button1,      tag,            {0} },
        { ClkTagBar,        MODKEY,       Button3,      toggletag,      {0} },
};

The structure of these button definitions might be confusing to new DWM users. The first column in the array will accept an integer, however for clarity sake an enum is used. This value will denote which of these windows the clicking event should apply to. The enums definition is located in the main DWM source file:

dwm.c

[...]
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
       ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
[...]

Furthermore, the eventmask simply gives the ability to require a modifier key to be held. The button is self explanatory (1 = Left, 2 = Center, 3, Right) and the function and argument simply specify any function defined within the scope of the program and the arguments that this function is supposed to receive.

Let’s cram XMenu in there!

From looking at the keyboard mappings we know, that the spawn function simply accepts a pointer to a null terminated constant char array, in order to execute the contained shell commands. This makes it easy to just add another char definition for our XMenu:

config.def.h

[...]
static const char *termcmd[]  = { "st", NULL };
static const char *dmenucmd[] = { "dmenu_run", NULL };
/* XMenu CMD */
static const char *xmenucmd[] = { "xmenu_run", "-d", NULL };
[...]

To call this command when we right-click on the desktop, we now just need to add an entry to the buttons array. This entry will define an action on the root window (ClkRootWin), without a key event mask, for the third (right) mouse button, which should call the spawn function with the arguments in our xmenucmd char array:

config.def.h

[...]
        { ClkRootWin,        0,        Button3,      spawn,      {.v = xmenucmd } },
};

Now save, make clean the directory, recompile and ba-boom! It works perfectly. And all that, without even editing any of the *.c files, only the basic header file, that any DWM user will be intimately familiar with!


Conclusion and Implications

This article has become alot longer than I wanted it to be, but after months of tinkering around with DWM and truly falling in love with it, I had to write an article. These little heureka! moments are, in my opinion, what makes DWM, suckless software and even open source software as a whole so beautiful. Being your own boss and solving your own problems in an efficient way, that even tailor made programs can’t quite solve as efficiently, is a great feeling!

My view of X11 desktop environments and computer usage as a whole has changed alot more over these past months as I had ever anticipated. Going back to anything else honestly feels like a step back, even if the alternatives are more feature packed or easier to use. The elitism factor, which permeates the linux / unix sphere as a whole might be a neccessary step, to ensure intelligent discussion. But it does hold back software projects like suckless from unleashing what they could bring to a larger subset of computer users and technology enthusiasts:

The feeling of self-sufficiency in a bleak, inoffensive, toddler-proof technological landscape, which borders on dystopia more and more with every passing year. It is ludicrous to expect your average Joe to tinker with window managers, when he is working, raising a family and paying off a second morrgage. But if schools were to give a generation of tech-savvy kids these tools to tinker and experiment with, instead of just teaching them the holy microsoft scripture of word, excel and maybe visual studio, it would be a net-benefit to society in my opinion.