XMobar allows configuring border position, as well as width:

{ border = BottomB
, borderColor = "#4F5B66"
, borderWidth = 1 }

I'm hoping to do the same in XMonad, but it seems borders are only configurable via the following properties:

{ borderWidth = 1
, normalBorderColor = "#4F5B66"
, focusedBorderColor = "#96B5B4" }

Even with XMonad.Layout.NoBorders, it seems this is not an option (or not a straightforward one).

In the end I would like to have a bottom border of one pixel which is always drawn and changes colour depending on focus. Is this currently possible, and how would I go about setting it up like that?


This question has been sufficiently answered in the GitHub issue I opened after this question received very little attention.

The problem with this is that xmonad doesn't draw its own borders; it just tells X how thick they should be and what colour.

[It is] possible to tell X to use certain patterns [with] the border_pixmap element in the XSetWindowAttributes structure.

If you assume all the caveats [described] in [https://tronche.com/gui/x/xlib/window/attributes/border.html] aren't actually there or don't mean anything, then you might conclude that [...] one could set a bottom-only border by specifying a very large pixmap that wraps around the whole window.

[As it stands, ] the graphics driver writers constantly break server-side borders, because only xmonad and dwm use them these days. And neither uses borderPixmap, so there's probably lots of bugs hidden there.

The take-away here is that, while it should be possible to use Window Attributes for this in theory, it's not a great idea. There is an alternative approach that might be better:

To get this result in xmonad, you'd need to have width 0 borders and then implement window decorations placing a coloured bar where you want the 'border'.

It's actually pretty easy to write an instance of the DecorationStyle class that will place a border-like decoration on one side of the window. If that side is the top or the bottom then the bar will be wide enough and the window's title text will be rendered in it, but that can be made a non-issue by setting text to the same colour as the bar or supplying an empty font.

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}

import qualified XMonad.StackSet as W
import XMonad.Layout.Decoration
import XMonad.Util.Types

data SideDecoration a = SideDecoration Direction2D
  deriving (Show, Read)

instance Eq a => DecorationStyle SideDecoration a where

  shrink b (Rectangle _ _ dw dh) (Rectangle x y w h)
    | SideDecoration U <- b = Rectangle x (y + fi dh) w (h - dh)
    | SideDecoration R <- b = Rectangle x y (w - dw) h
    | SideDecoration D <- b = Rectangle x y w (h - dh)
    | SideDecoration L <- b = Rectangle (x + fi dw) y (w - dw) h

  pureDecoration b dw dh _ st _ (win, Rectangle x y w h)
    | win `elem` W.integrate st && dw < w && dh < h = Just $ case b of
      SideDecoration U -> Rectangle x y w dh
      SideDecoration R -> Rectangle (x + fi (w - dw)) y dw h
      SideDecoration D -> Rectangle x (y + fi (h - dh)) w dh
      SideDecoration L -> Rectangle x y dw h
    | otherwise = Nothing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.