Saturday, October 23, 2021

Setting up Xmonad on a Lenovo ThinkPad X1 Carbon: Getting Started

From time to time, I have profoundly bad ideas. One of those ideas is to change out the window manager on a Linux PC.

For many tasks (such as maintaining this blog), I keep a Lenovo ThinkPad X1 Carbon running Linux. It’s been a good little workhorse, running Ubuntu 20.04. I decided to switch my window manager to Xmonad, because I enjoy fast manipulation of my windows without needing to tell the window manager where they should live.

In principle, this should be very straightforward. In practice, it turns out that switching out your window manager causes a wide variety of seemingly-unrelated things to break. As best I understand it, this is because several basic “housekeeping” tasks of a desktop Linux environment actually route through the window manager, and when the WM goes away, the configurations that launch those tools goes with it. Here’s a short list of things that no longer “just work” when you switch off (I keep discovering more as I go):

The rest of this post will go into how to get a basic Xmonad setup done. Over the next while, I’ll fill in more information on how to get the remaining functionality back without Canonical’s default window manager in place.

First steps

I drew heavily from a beginner’s guide to Xmonad, which generally steered me in the right direction. I was able to install the relevant components with apt-get. This got me a configuration running with Xmonad, Xmobar (to display content at the top), and Stalonetray (an icon tray, which is necessary for some X11 apps to have a place to show system status).

After finishing this config, some things worked but some took some banging on. In particular,

  • Xmonad has been updated since this guide was released, and the way “docks” attach has changed. My xmonad.sh factors this change in.
  • xfce4-power-manager icon is black-on-black, so I thought it was missing. It was simply invisible in the default all-black color scheme of the top-bar. Switching to a dull grey helped the missing icons appear. Once I knew what the issue was, I was able to install lxappearance and run it to change the icon theme configuration; switching to “Ubuntu-Mono-Dark” provided an icon that was visible.
  • To attempt to integrate with the sound control buttons on the ThinkPad, I pulled in “xmonad-extras,” which integrates against “Third party extensions for xmonad with wacky dependencies” (I’m leaving it as an exercise for the reader whether ‘controlling volume via keyboard’ should be considered “wacky,” but you do you). This proved more challenging than I expected because apt-get actually knows this package as libghc-xmonad-extras-dev, but once I found it it worked fine (though I will probably extract it for reasons I’ll get into when I drill open audio).

Put it all together and the end result so far isn’t terrible!

Screenshot of my desktop with xmonad running: status bar at top, three windows open
I don't expect it to win any awards, but it's pretty functional


The Configs

Below are the relevant config files I have so far.

~/.xmonad/xmonad.hs:

import Graphics.X11.ExtraTypes.XF86
import XMonad
import XMonad.Actions.Volume
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks (ToggleStruts(..),avoidStruts,docks,manageDocks)
import XMonad.Util.Dzen
import XMonad.Util.Run(spawnPipe)
import XMonad.Util.EZConfig(additionalKeys)
import System.IO

alert = dzenConfig return . show

main = do
    xmproc <- spawnPipe "xmobar"

    xmonad $ docks defaultConfig
        { manageHook = manageDocks <+> manageHook defaultConfig
        , layoutHook = avoidStruts  $  layoutHook defaultConfig
        , logHook = dynamicLogWithPP xmobarPP
                        { ppOutput = hPutStrLn xmproc
                        , ppTitle = xmobarColor "green" "" . shorten 50
                        }
        , modMask = mod4Mask     -- Rebind Mod to the Windows key
        } `additionalKeys`
        [ ((mod4Mask .|. shiftMask, xK_z), spawn "xscreensaver-command -lock; xset dpms force off")
        , ((controlMask, xK_Print), spawn "sleep 0.2; scrot -s")
        , ((0, xK_Print), spawn "scrot")
        , ((mod4Mask .|. shiftMask, xK_f), sendMessage ToggleStruts)
        -- Volume control
        , ((0, xF86XK_AudioMute), toggleMute >> return ())
        , ((0, xF86XK_AudioLowerVolume), lowerVolume 2 >>= alert)
        , ((0, xF86XK_AudioRaiseVolume), raiseVolume 2 >>= alert)
        -- App Launchers
        , ((mod4Mask .|. shiftMask, xK_w), spawn "google-chrome")
        , ((mod4Mask .|. shiftMask, xK_e), spawn "emacsclient -c")
        ]

~/.xmobarrc (dropped the lookups for eth network state and switched to Pittsburgh weather):

Config { font = "-*-Fixed-Bold-R-Normal-*-13-*-*-*-*-*-*-*"
        , borderColor = "black"
        , border = TopB
        , bgColor = "#333333"
        , fgColor = "grey"
        , position = TopW L 100
        , commands = [ Run Weather "KPIT" ["-t","<tempC>C","-L","18","-H","25","--normal","green","--high","red","--low","lightblue"] 36000
                        , Run Network "wlan" ["-L","0","-H","32","--normal","green","--high","red"] 10
                        , Run Cpu ["-L","3","-H","50","--normal","green","--high","red"] 10
                        , Run Memory ["-t","Mem: <usedratio>%"] 10
                        , Run Swap [] 10
                        , Run Date "%a %b %_d %Y %H:%M:%S" "date" 10
                        , Run StdinReader
                        ]
        , sepChar = "%"
        , alignSep = "}{"
        , template = "%StdinReader% | %cpu% | %memory% * %swap% | %wlan% }{<fc=#ee9a00>%date%</fc> | %KPIT% "
        }

~/.stalonetrayrc:

decorations none
transparent false
dockapp_mode none
geometry 5x1-240+0
max_geometry 10x1-325-10
background "#333333"
kludges force_icons_size
grow_gravity NE
icon_gravity NE
icon_size 12
sticky true
#window_strut none
window_type dock
window_layer bottom
#no_shrink false
skip_taskbar true

~/.xsessionrc:

#!/bin/bash

# Load resources

# this sets your background wallpaper. Without it, xmonad doesn't know how to redraw when we
# navigate to a workspace with nothing on it.
feh --bg-scale /usr/share/backgrounds/warty-final-ubuntu.png &
# Power manager, so you can see your battery
xfce4-power-manager &

# volume icon in tray
pasystray &

xrdb -merge .Xresources

# Set up an icon tray
stalonetray &

# Fire up apps
emacs --daemon
xscreensaver -no-splash &
udiskie &

if [ -x /usr/bin/nm-applet ] ; then
   nm-applet --sm-disable &
fi

exec xmonad

More to come

In subsequent posts, I’ll go into detail on managing power, sound, monitor configs, and Bluetooth.

No comments:

Post a Comment