Skip to content

Custom Lua API

Bobby Comet edited this page Jul 31, 2026 · 1 revision

Custom Lua API & Drawing Engine

Custom Lua nodes and the generated render.lua share one draw pipeline. Your code runs inside Conky’s Lua VM with Cairo, not inside Conky Studio’s Python process.


Entry points

Hook Conf Role
main_draw lua_draw_hook_post = 'main_draw' Once per Conky refresh after Conky’s own pass
mouse_handler lua_mouse_hook (if clickable nodes exist) Click / mouse events for explicit regions

Studio generates the wrapper that:

  1. Refreshes source caches as needed
  2. Obtains a Cairo surface / context
  3. Calls each visible visual’s draw body (including Custom Lua) in z-order
  4. Releases the surface if this frame created it

Exposed drawing environment

Inside a Custom Lua node body (and generated visual bodies), treat these as available:

Name Meaning
cr Current Cairo context for this frame
W Window / canvas width (pixels)
H Window / canvas height (pixels)

Do not create your own Xlib surface or destroy Conky-owned surfaces. Surface setup is handled by the framework’s get_draw_surface() logic:

  • Prefer conky_surface() when present (Wayland layer-shell / modern Conky) — not destroyed by theme code
  • Fallback: cairo_xlib_surface_create(...) on older builds — framework destroys what it created

Custom Lua should only draw with the provided cr.

Coordinates

  • Origin is the Conky window’s top-left (same as other Studio visuals).
  • Node x / y offsets from the property panel shift the block without editing Lua (applied by the generator around your body when configured).
  • Use W / H for responsive layouts.

Framework helpers (typical)

Exact names ship in FRAMEWORK_LUA inside lua_framework.py / generated render.lua. Common utilities include:

Helper Role
clamp / lerp Math
safe_parse / safe_number Guarded evaluation
read_kv_cache(path) Read daemon/exec script cache files
load_image_cached(path) PNG via Cairo; SVG via RSVG if built; caches misses as false
draw_image_fit(cr, img, x, y, size, rotation_deg, opacity) Aspect-fit draw with optional rotate/alpha
rounded_rect(cr, x, y, w, h, r) Path helper
resolve_net_iface() Best-effort default interface

Rely on these when possible so behaviour matches Image/Icon nodes and survives missing files without spamming logs every frame.


Binding Custom Lua in the graph

Property Role
code Your Cairo Lua statements
x, y Offset for this node’s drawing

Custom Lua is a visual: it participates in Layers (order, visibility, lock). Hidden nodes are omitted from codegen.

You can still use other nodes for data: e.g. wire sources into Text/Gauges and only use Custom Lua for a special effect. There is no automatic injection of arbitrary node values into Custom Lua unless the generator substitutes props you declare (plain Custom Lua is primarily free-form text).

Plugin visuals

Plugin packs supply lua_draw_body with {property} placeholders substituted at build time (colours → r, g, b). Same cr / W / H contract. Optional lua_helpers are emitted once per plugin type.


Event handling (clicks)

When any node defines a click region + command:

  1. Conf enables lua_mouse_hook.
  2. Generated mouse_handler tests event coordinates against rectangles.
  3. Matching region runs the associated shell command (same trust model as theme scripts).

Regions are explicit boxes (x, y, w, h), not auto-derived from every shape’s path. That matches real-world music-control / hotspot patterns.


Performance notes

Practice Why
Cache images via load_image_cached Avoid reloading PNG/SVG every frame
Avoid heavy work every frame Prefer script caches + light Cairo
Don’t print every frame Use one-time miss markers like the framework
Respect stats_hz vs fps Data refresh ≠ draw rate (Canvas settings)

Minimal Custom Lua example

-- Assumes cr, W, H are in scope (Studio wrapper).
cairo_set_source_rgba(cr, 0.3, 0.82, 0.77, 1)
cairo_arc(cr, W * 0.5, H * 0.5, 40, 0, 2 * math.pi)
cairo_fill(cr)

Safety & trust

Custom Lua and plugin Lua run inside Conky with the same privileges as any theme (io.popen / os.execute may exist). Treat imported or community Lua like software you run on your machine.


Debugging

  1. Live Preview log (Studio) or terminal when using ./start.sh
  2. print(...) sparingly — shows in Conky’s log
  3. If the whole HUD dies, check surface/ownership and syntax errors in the generated render.lua
  4. Compare with a empty Custom Lua + one built-in Text node to isolate session vs script issues

See Theme Architecture & Codegen for how bodies are ordered inside main_draw.

Clone this wiki locally