aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-17 12:07:46 +0200
committerDanilo M. <danix@danix.xyz>2026-09-17 12:07:46 +0200
commit64e8f20ce3a27dfc6cc2f37ae449dcb5eb91e7a9 (patch)
tree6081ba303ad2fdead331220f29e9a211d47be715
parentcfbd02e85f039a557cf6561b84b58097f70041d4 (diff)
downloadconky-theme-udt-64e8f20ce3a27dfc6cc2f37ae449dcb5eb91e7a9.tar.gz
conky-theme-udt-64e8f20ce3a27dfc6cc2f37ae449dcb5eb91e7a9.zip
test: add an offscreen widget render harness
-rw-r--r--test/render.lua87
1 files changed, 87 insertions, 0 deletions
diff --git a/test/render.lua b/test/render.lua
new file mode 100644
index 0000000..7d48d0e
--- /dev/null
+++ b/test/render.lua
@@ -0,0 +1,87 @@
+-- Render a widget to a PNG without conky.
+--
+-- Conky ships its Cairo bindings as a loadable module, so a widget's draw()
+-- can be called against an image surface from plain Lua. That turns
+-- edit-install-restart-toggle-screenshot into one command, which is how the
+-- weather card's proportions were fixed.
+--
+-- lua test/render.lua weather 16 12 3 5 /tmp/w.png
+--
+-- Caveat: this crops to the single card. It says nothing about how the card
+-- looks NEXT to its neighbours, which is a real failure mode (the weather
+-- card's type once looked fine here and tiny beside the clock). Check the
+-- live dashboard before believing anything about relative size.
+
+package.cpath = '/usr/lib64/conky/lib?.so;' .. package.cpath
+package.path = './?.lua;' .. package.path
+require 'cairo'
+
+local widget_name = arg[1] or error('usage: render.lua <widget> <cols> <rows> <w> <h> <out.png>')
+local COLS = tonumber(arg[2]) or 8
+local ROWS = tonumber(arg[3]) or 6
+local wspan = tonumber(arg[4]) or 2
+local hspan = tonumber(arg[5]) or 3
+local out = arg[6] or '/tmp/widget.png'
+
+local GAP, MARGIN = 16, 28
+local sw, sh = 2560, 1080
+
+-- The palette, read from the rendered conky.conf exactly as dashboard.lua
+-- does, so the PNG uses the real scheme rather than invented colours.
+local function config_colors()
+ local path = os.getenv('HOME') .. '/.config/conky/conky.conf'
+ local f = io.open(path, 'r')
+ if not f then return {} end
+ local src = f:read('*a')
+ f:close()
+ local c = {}
+ for k, v in src:gmatch("([%w_]+)%s*=%s*'(#%x%x%x%x%x%x)'") do c[k] = v end
+ return c
+end
+
+local CFG = config_colors()
+
+local function hex(s, fallback)
+ local r, g, b = tostring(s or ''):match('^#?(%x%x)(%x%x)(%x%x)$')
+ if not r then return fallback or { 1, 0, 1 } end
+ return { tonumber(r, 16) / 255, tonumber(g, 16) / 255, tonumber(b, 16) / 255 }
+end
+
+local colors = {
+ heading = hex(CFG.color1), label = hex(CFG.color2),
+ border = hex(CFG.color3), rule = hex(CFG.color3),
+ value = hex(CFG.color4), highlight = hex(CFG.color5),
+ ok = hex(CFG.color6), critical = hex(CFG.color7),
+ warning = hex(CFG.color8, { 0.88, 0.69, 0.41 }),
+ body = hex(CFG.default_color),
+ surface = hex(CFG.default_shade_color),
+}
+
+local cw = (sw - MARGIN * 2 - GAP * (COLS - 1)) / COLS
+local ch = (sh - MARGIN * 2 - GAP * (ROWS - 1)) / ROWS
+local rect = {
+ x = MARGIN, y = MARGIN,
+ w = cw * wspan + GAP * (wspan - 1),
+ h = ch * hspan + GAP * (hspan - 1),
+}
+
+local surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect.w + 40, rect.h + 40)
+local cr = cairo_create(surf)
+-- A backdrop close to the dashboard's own, so contrast reads honestly.
+local bg = colors.surface
+cairo_set_source_rgb(cr, bg[1] * 0.6, bg[2] * 0.6, bg[3] * 0.7)
+cairo_paint(cr)
+cairo_translate(cr, 20 - rect.x, 20 - rect.y)
+
+local ok, mod = pcall(require, 'widgets.' .. widget_name)
+if not ok then
+ print('cannot load widget ' .. widget_name .. ': ' .. tostring(mod))
+ os.exit(1)
+end
+local drew, err = pcall(mod.draw, cr, rect, colors)
+if not drew then print('DRAW ERROR: ' .. tostring(err)) end
+
+cairo_destroy(cr)
+cairo_surface_write_to_png(surf, out)
+cairo_surface_destroy(surf)
+print(string.format('%s at %dx%d on a %dx%d grid -> %s', widget_name, wspan, hspan, COLS, ROWS, out))