Cairo
Allows you to render custom content using the Lua and the Cairo drawing library. This is an advanced feature which provides a powerful escape hatch, allowing you to fetch data and render anything using an embedded scripting environment.
Scripts are automatically hot-reloaded.

Configuration
Type:
cairo
| Name | Type | Default | Description |
|---|---|---|---|
path | string | null | The path to the Lua script to load. |
frequency | float | 200 | The number of milliseconds between each draw call. |
width | integer | 42 | The canvas width in pixels. |
height | integer | 42 | The canvas height in pixels. |
JSON
{ "center": [ { "type": "cairo", "path": ".config/ironbar/clock.lua", "frequency": 100, "width": 300, "height": 300 } ]}TOML
[[center]]type = "cairo"path = ".config/ironbar/clock.lua"frequency = 100width = 300height = 300YAML
center:- type: cairo path: .config/ironbar/clock.lua frequency: 100 width: 300 height: 300Corn
let { $config_dir = ".config/ironbar" $cairo = { type = "cairo" path = "$config_dir/clock.lua" frequency = 100 width = 300 height = 300 }} in { center = [ $cairo ]}{ "center": [ { "type": "cairo", "path": "$config_dir/clock.lua", "frequency": 100, "width": 300, "height": 300 } ]}center: - type: cairo path: $config_dir/clock.lua frequency: 100 width: 300 height: 300[[center]]type = "cairo"path = "$config_dir/clock.lua"frequency = 100width = 300height = 300Script
Every script must contain a function called draw.
This takes a single parameter, which is the Cairo context.
Outside of this, you can do whatever you like.
The full lua stdlib is available, and you can load in additional system packages as desired.
The most basic example, which draws a red square, can be seen below:
function draw(cr) cr:set_source_rgb(1.0, 0.0, 0.0) cr:paint()endA longer example, used to create the clock in the image at the top of the page, is shown below:
Circle clock
function get_ms() local ms = tostring(io.popen('date +%s%3N'):read('a')):sub(-4, 9999) return tonumber(ms) / 1000end
function draw(cr) local center_x = 150 local center_y = 150 local radius = 130
local date_table = os.date("*t")
local hours = date_table["hour"] local minutes = date_table["min"] local seconds = date_table["sec"] local ms = get_ms()
local label_seconds = seconds seconds = seconds + ms
local hours_str = tostring(hours) if string.len(hours_str) == 1 then hours_str = "0" .. hours_str end
local minutes_str = tostring(minutes) if string.len(minutes_str) == 1 then minutes_str = "0" .. minutes_str end
local seconds_str = tostring(label_seconds) if string.len(seconds_str) == 1 then seconds_str = "0" .. seconds_str end
local font_size = radius / 5.5
cr:set_source_rgb(1.0, 1.0, 1.0)
cr:move_to(center_x - font_size * 2.5 + 10, center_y + font_size / 2.5) cr:set_font_size(font_size) cr:show_text(hours_str .. ':' .. minutes_str .. ':' .. seconds_str) cr:stroke()
if hours > 12 then hours = hours - 12 end
local line_width = radius / 8 local start_angle = -math.pi / 2
local end_angle = start_angle + ((hours + minutes / 60 + seconds / 3600) / 12) * 2 * math.pi cr:set_line_width(line_width) cr:arc(center_x, center_y, radius, start_angle, end_angle) cr:stroke()
end_angle = start_angle + ((minutes + seconds / 60) / 60) * 2 * math.pi cr:set_line_width(line_width) cr:arc(center_x, center_y, radius * 0.8, start_angle, end_angle) cr:stroke()
if seconds == 0 then seconds = 60 end
end_angle = start_angle + (seconds / 60) * 2 * math.pi cr:set_line_width(line_width) cr:arc(center_x, center_y, radius * 0.6, start_angle, end_angle) cr:stroke()
return 0endInitialization
You can optionally create an init.lua file in your config directory.
Any code in here will be executed once, on bar startup.
As variables and functions are global by default in Lua, this provides a mechanism for sharing code between multiple modules.
Styling
| Selector | Description |
|---|---|
.cairo | Cairo widget container. |
For more information on styling, please see the styling guide.