My Xmonad configuration

— Why we should care about Open Source

2021-01-21

I like applications that give me the freedom to do what I could not else do, or could not easily do. Such applications empower the user and are, unfortunately, at odds with current UI/UX trends as well as the commercialization of software.

This is why I appreciate xmonad, a tiling window manager. xmonad allows me, with simple means, to tailor a user-specific general UI/UX for windows and workspaces. I believe this is how applications - contrary to the current trend - should behave, or could behave with a knowledgeable user. And I also think there is no real opposition to commercial interests, just an opposition to the prevalent Hollywood ideology that hides this from us (including me) most of the time.

In proprietary operating systems you could most likely hide parts of the systems GUI (the main area from where we start other applications), but not fully.

The current trend in UX design is depersonalization; producing a standardized user experience. Most likely this stems from big companies wanting to have control of the effects of the application for various reasons, but also because of reasons related to marketing. If Windows would allow you to change everything in the GUI it would no longer be Windows and in a way, you would not use a Microsoft product.

I don’t see this trend as a necessary state of affairs, but I believe it’s the prevalent state of affairs.

Who wouldn’t love a company with the confidence to allow the user this kind of freedom? In the long run, I think those companies that can find a sound balance between marketing, making money, and allowing users reasonable freedom in different respects will be the most successful.

Without freedom, a portion of the user will keep wondering how they could have tailored the user experience according to personal preference and purposes. With freedom, people could do this but the majority of users would not, and choose a more standardized version (which is fine, and most of the time the best choice).

There is nothing special about my xmonad configuration, but I want to share it and shortly describe how and why I’ve made certain choices.

What guiding principle did I use in tailoring my system using xmonad? The short answer is minimalism.

I don’t use xmonad with xmobarr, meaning I don’t have a status bar. This is a personal preference: I don’t like the distraction a status-bar brings about, and I do not need to constantly see my CPU usage, my current download speed, and the weather, etc.

If I did not have a practical solution for workspaces, I would most likely use xmobar, but only to display all available workspaces and what workspace I currently use. What about time? I display time in tmux (hours and minutes).

All configurations of xmonad are made with Haskell and the powerful xmonad API. I use a grid select layout for switching workspace. To start non-command line applications I use rofi (an application similar to dmenu).

This is a random tour displaying the features mentioned:

To most people, my setup is too minimalistic. But the great thing about a window-manager such as xmonad is that you’re supposed to custom it, make it your own. This is why you start with an empty configuration file and a blank screen.

My setup spans 110 lines including comments. I begun with a configuration proposed by the people behind xmonad, removed parts, changed bits here and there, and added some functionality.

{-# LANGUAGE UnicodeSyntax #-}

import qualified Data.Map as M
import Data.Monoid
import System.Exit
import System.IO
import XMonad
import XMonad.Actions.GridSelect
import XMonad.Hooks.EwmhDesktops
import qualified XMonad.StackSet as W
import XMonad.Util.EZConfig
  ( additionalKeys
  , additionalKeysP
  , additionalMouseBindings
  )
import XMonad.Util.SpawnOnce

myGSConfig =
  (buildDefaultGSConfig myColorizer)
    { gs_font = "xft:Jetbrains Mono:size=20:antialias=true"
    , gs_cellwidth = 400
    , gs_cellheight = 80
    , gs_navigate = navNSearch
    }

myColorizer w a =
  if a
    then return ("#005577", "#eeeeee")
    else return ("#222222", "#bbbbbb")

myKeys conf@(XConfig {XMonad.modMask = modm}) =
  M.fromList $
    -- launch a terminal
  [ ((modm .|. shiftMask, xK_Return), spawn $ XMonad.terminal conf)
    -- change keyboard layout
  , ((modm, xK_s), spawn "~/.local/bin/layout")
    -- select workspaces
  , ((modm .|. shiftMask, xK_g), gridselectWorkspace myGSConfig W.view)
    -- launch rofi
  , ((modm, xK_p), spawn "rofi -show run")
    -- close focused window
  , ((modm .|. shiftMask, xK_c), kill)
     -- Rotate through the available layout algorithms
  , ((modm, xK_space), sendMessage NextLayout)
    --  Reset the layouts on the current workspace to default
  , ((modm .|. shiftMask, xK_space), setLayout $ XMonad.layoutHook conf)
    -- Resize viewed windows to the correct size
  , ((modm, xK_n), refresh)
    -- Move focus to the next window
  , ((modm, xK_Tab), windows W.focusDown)
    -- Move focus to the next window
  , ((modm, xK_l), windows W.focusDown)
    -- Move focus to the previous window
  , ((modm, xK_h), windows W.focusUp)
    -- Move focus to the master window
  , ((modm, xK_m), windows W.focusMaster)
    -- Swap the focused window and the master window
  , ((modm, xK_Return), windows W.swapMaster)
    -- Swap the focused window with the next window
  , ((modm .|. shiftMask, xK_j), windows W.swapDown)
    -- Swap the focused window with the previous window
  , ((modm .|. shiftMask, xK_k), windows W.swapUp)
    -- Shrink the master area
  , ((modm, xK_Left), sendMessage Shrink)
    -- Expand the master area
  , ((modm, xK_Right), sendMessage Expand)
    -- Quit xmonad
  , ((modm .|. shiftMask, xK_q), io (exitWith ExitSuccess))
  ]

myLayout = tiled ||| Mirror tiled ||| Full
  where
    nmaster = 1
    tiled = Tall nmaster delta ratio
    ratio = 1 / 2
    delta = 3 / 100

myManageHook =
  composeAll
    [ className =? "Peek" --> doFloat
    , className =? "vokoscreenNG" --> doFloat
    , resource =? "desktop_window" --> doIgnore
    ]

myStartupHook = do
  spawnOnce "nitrogen --restore &"
  spawnOnce "compton &"
  spawnOnce "feh --bg-fill ~/Documents/Pictures/GckcfrL.jpeg"

main =
  xmonad $
  ewmh
    def
      { terminal = "alacritty"
      , focusFollowsMouse = True
      , clickJustFocuses = False
      , borderWidth = 1
      , modMask = mod4Mask
      , workspaces =
          ["web", "dev1", "work", "dev2", "sh", "com", "txt", "music", "dev3"]
      , normalBorderColor = "#000000"
      , focusedBorderColor = "#dddddd"
      , keys = myKeys
      , mouseBindings = mempty
      , layoutHook = myLayout
      , manageHook = myManageHook
      , handleEventHook = mempty <+> fullscreenEventHook
      , logHook = return ()
      , startupHook = myStartupHook
      }

About | Archive