hacking on Qtile: painting complex borders

The years of checking up on the unixporn subreddit has imprinted in me a want for a unique and aesthetic desktop. One of the advantages I saw in the Qtile window manager (while I was rapidly hopping between WMs) is how easy it is to bend to my will, being made in Python. Recently I set out to satisfy my desire for more than just single colour, single line window borders.

The result of this endeavour has two parts. The first is a PR I submitted last week to Qtile that lets users pass their layouts a list of border colours and a list of border widths to paint multiple borders on their windows. In my head it was a long time coming, having nice windows like these:

Window with triple borders

The code accepts any number of border colours and widths, so if you really wanted to, you could have borders like these:

Window with a shitload of borders

Has user freedom come too far?

The PR also aimed to unify all border-drawing code into one callable. This leads to the second development: you can override this callable - xcbq.Window.paint_borders of Qtile's X11 backend - and replace the border-painting logic with your wildest dreams.

Normally, this method would loop over the configured colours and widths, using them to draw increasingly small filled rectangles centred on a pixmap that will be used to paint the window's borders. This results in the multi-border effect above. A function we define to override this method will therefore have access to a list of colours, as well as the window's geometry including border width, and a canvas - the pixmap.

The paintbrush is tycho0's xcffib, which provides Python bindings to XCB. The xcffib.xproto module gives us the functions we need to create some shapes and paint them to our pixmap, which are reminiscent of their C counterparts such as xcb_poly_fill_rectangle from xcb.xproto.h.

Using this information, we can do whatever we want. A simple example would be to draw a couple of trapeziums (trapezia? thefreedictionary suggests either, TIL) using xcffib.xproto.POINT and paint them using and FillPoly in two of the colours. This can create this picture frame-like appearance:

Window with frame

Pretty cool, no? Maybe too simple.

With some faffing around in GIMP on a screenshot of the Common Desktop Environment (CDE), I decoded the design for their old-school 3D borders. I'm aware I could have hunted down the source code to find out how their borders are drawn but where's the fun in that?

The design is largely made of 1-pixel-wide lines, so we can use xcffib.xproto.POINT as before to join them up, then PolyLine to paint them to the pixmap. With a main colour, a lighter shade and a darker shade, we can get this result:

Window with triple borders

Pretty groovy borders if you ask me, and it's a design I can use without sacrificing a solid, modern window manager.

I've added these to my Qtile plugin repository qtools, from which they can be used by simply importing and enabling the borders plugin with the desired style:

import qtools.borders
borders.enable("CDE")

The plugins might also serve as a simple starting point to implement more border designs.

I'd love to make a small library of different designs that can be used to make borders but my own creativity is limited. Let me know if you have any design ideas that you'd want implemented for your own Qtile config!

avatar

Welcome to my blog!

I write about open source software that I stumble across surfing the web.

Some of my main interests are self-hosting, privacy tools, and anything to do with ricing.

- Matt -


Posts - Code - Blogroll - CV