New in Barium & ChessLab, 2026/Q1
In the tradition of “shut up and write the code” there have been no recent updates on what I’ve been up to. However, the pile of finished stuff is now high enough to call it a milestone or two, so I finally got down to compile a summary for those of you wishing to follow along.
Barium
As a reminder: Barium is an X Window System toolkit natively implemented in Common Lisp, with first class OpenGL support and many exciting features.
X Selection support
The flagship feature is arguably the addition of selections support. In case you are not familiar with X Window System terminology, selections are the inter-client mechanism underpinning copy & paste operations.

Barium happily interchanging data with Zutty and LibreOffice
The protocol is implemented by methods of the newly added
selection-handler class, which interested widgets should inherit.
Since I already implemented this for my GPU-accelerated X terminal
emulator Zutty, I could do a more or less direct port from
C++ to
Common
Lisp.
Minor changes were necessary to widen its scope from serving a
single-widget application to supporting a full-blown widget toolkit.
Still, it might make an interesting case study comparing closely
related code across very different programming languages.
On top of the support provided by selection-handler, the text entry
and multi-line textedit widgets have been endowed with cut/copy/paste
interactions, in line with the usual UNIX desktop interface
conventions:
- left-click and drag selects text;
- button release on drag end sets the primary selection;
- middle-click inserts the primary selection at the location defined by the mouse pointer (to which the cursor will jump due to the click);
- Shift+Insert inserts the primary selection at the cursor location;
- Ctrl+C sets the clipboard selection to the content of the selected region;
- Ctrl+X sets the clipboard selection while also cutting the region from the widget’s text;
- Ctrl+V inserts the clipboard selection at the cursor location;
- Shift+arrows manipulate the endpoint of the current selection, or start a selection from the current cursor position if there is none.
Modal windows
Support has been added for creating modal windows. Such windows act similar to popups with input grabs, but allow the user to interact with other X clients, just not with other interface elements of the same program.
Passing the initarg :modal-p t sets up a window as modal. There can
be multiple modal windows opened by the application. These are
stacked; the last one opened is considered the active one.
In case there is an active modal window, the only windows allowed to receive focus are itself and any non-modal windows opened by it. On user interaction, focus is diverted away from any other windows to the active modal window.
File dialog windows are now created as modal; generic message dialogs
now provide the :modal-p keyword argument to set them modal.
Inactive widgets
Support has been added for inactive (greyed out, unresponsive)
widgets. Such widgets can be set active or inactive by calling
set-active on them, or via the initarg :active. When inactive, the
widget is greyed out and user interaction with it is disabled.
The following widgets support being set (in)active:
button, checkbutton, combobox, entry,
listbox, menu-item, menubar-item,
hslider, vslider, textedit
The generic functionality is contained by the newly added mixin class
active-settable, which individual widgets inherit – and that’s
all! It is a testament to the power of CLOS that this feature could be
implemented in such an orthogonal way, in less than 40
lines
of Lisp!
Even so, a small amount of bespoke logic is added to:
- disable mouse-over highlight when inactive for button & checkbutton;
- set the X cursor based on editability (focus enabled and active) for entry and textedit;
- allow the combobox (a composite) to be (in)activated as one widget.
The test app ‘Inspector’ is amended to allow runtime switching of any supported widget, which makes for an interactive means of testing:

Menu system improvements
- Menu items can also be inactive via dynamically evaluating the
closure supplied by the initarg
:active-fn, easily automating the task of setting the availability of a menu item according to program state. Worth noting is that the hotkey bound to the item will not be inactivated, so in that case the signal handler must be gated with the same logic. - Dynamically generated menus: useful for menus where content is easiest generated dynamically, such as an “Open Recent” submenu offering recently opened documents. (Hint: see ChessLab for an example implementation!)
- menu-item: added
fnslot to support direct evaluation of closures (as opposed to emitting a signal); bothfnandsig(signal to emit on selection) may be used simultaneously. - Improved usability of cascading menus: By adding a small timeout before closing an open submenu, we allow the user to sweep the pointer across sibling items (that would normally close the submenu) in order to reach the items in the submenu. Previously, the user had to take care not to hover the mouse over sibling items, or the submenu would close immediately.
config-store: save and load props to/from file
This can be used by applications to persist configuration, settings, or whatever data they want to keep around between program runs. It is used by ChessLab to remember display (board and piece sets) as well as engine settings.
Various small fixes and enhancements
- Correct handling of child widgets destroyed in a grid container, enabling dynamic UIs where widgets are added/removed in response to user action.
- Asynchronous invocation of popup-dialog & menu-item handlers, so popups will be closed and the X input grab will be lifted even if the user-supplied handler crashes.
- Window handling fixes to protect against races when destroying an as-yet-unmapped modal window, or user code closing the same window multiple times.
- Still more stuff; feel free to check the commit log!
ChessLab
ChessLab is a desktop application for chess players and chess enthusiasts. It is written in Common Lisp and uses Barium for its GUI. ChessLab doubles as a testbed for Barium development and a flagship application showcasing the capabilities of the toolkit.
Position editor
This newly added dialog brings the much needed ability to enter arbitrary positions, essential when dealing with chess puzzles, positions from a chess book, etc.
The dialog can be opened from the menu (Board → Edit position…) or via the associated hotkey. The menu item is inactive unless the game is empty (no moves added yet).

The position editor is primarily keyboard-driven, augmented by the controls on the right. It is recommended to begin with the position on the board, and then adjust the parameters as needed.
Board editing is based on the FEN notation - keying in the piece placement part of a FEN will set it up on the board. However, the editor can also be used in a more flexible manner. The below functions can be freely exercised in any order:
- Move the current square by clicking on the board or using the arrow keys.
- Insert a piece by clicking its button, or pressing the corresponding key. The current square is advanced to the right.
- Number keys 1-8 erase that many squares and move right, within a single rank.
- Backspace erases and moves backward; delete erases in place.
- The slash key (‘/’) moves to the start of the next rank.
A separate help window with the above usage summary can be opened via clicking on the ‘?’ button, or pressing the ‘?’ key.
The position editor gives human-readable feedback whenever it contains an invalid position (such as a missing king, inactive side in check, bogus castling rights, etc). Such positions can be entered into ChessLab, but you won’t be able to analyse them via the engine.
PGN tag viewer/editor
Available from the menu (Game → Edit tags…) or via the associated hotkey, this new dialog offers a way to view and edit the tags associated with each game in a PGN.

New tags can be added by selecting them from the combo box and clicking ‘Add’; existing non-mandatory tags can be removed by clicking on the red X to their right. This dialog makes use of the dynamic capabilities of Barium, creating or deleting child widgets in response to user action.
Annotations editor
Available from the menu (Notation → Move annotations…) or via the associated hotkey, this new dialog offers viewing and altering the set of annotations associated with each move.

In contrast to the two other editor dialogs above, this editor is not modal. This is to support a workflow where the user leaves the annotations editor open besides the main ChessLab window, while browsing through moves (or even games). The editor is kept up to date with changing positions; any changes made in the editor propagate seamlessly without the need for extra button clicks.
Guarding against, and explaining illegal positions
The program allows so-called illegal positions (such as a board without kings) but guards the engine from seeing such a position as that might result in undefined behaviour for UCI engines (see this Stockfish FAQ item). If such a position is brought up, engine analysis is disabled and a human-friendly explanation of why the position is illegal is displayed.
Incremental PGN loader
PGN files with several thousands of games can take a couple dozen seconds to load. Previously, this was done in a blocking manner freezing the application, which got annoying above ~500 games. No longer so:

The PGN loader code has been refactored into continuation-passing style, allowing the main program to drive the loading process via repeatedly calling a worker function. This worker is plugged into the Barium event loop as an “idle function” that does work on each loop iteration as long as there is work to be done, while keeping the rest of the application responsive. As a bonus, there is now a visual indication of progress, as well as a button to cancel an ongoing load operation.
This PGN loader plus ChessLab’s UCI engine integration demonstrate how Barium’s event loop facility supports asynchronous computations in a single thread while keeping the UI responsive.
Various small features
- Persist application settings and properties to chesslab.conf placed
under
$XDG_CONFIG_HOMEor$HOME/.configif unset. This employs Barium’s config-store persistence feature mentioned above. - Offer recently opened files under the PGN → Open Recent… submenu, by means of a dynamically generated menu (see above).
Conclusion
Now that I went through the above list, it is very clear that this post has been long overdue. It also speaks volumes about the insane productivity offered by this tech stack, as mentioned in my previous post.
Barium is still far from complete, and it will never be the shiniest toolkit out there. But it is now clearly good enough to support many different types of interesting desktop applications, and its simple, lispy API lets me express GUI ideas in a concise way.
I reckon that ChessLab is now complete with the most essential features, so it could be useful for real chess players looking for a basic app. In case you tried (or used!) it in any capacity, I would love to hear from you!