Skip to content

Multi window support

Bobby Comet edited this page Aug 23, 2026 · 1 revision

Multi-Window & Scenes in Conky Studio

This wiki explains how multi-window/multi-monitor support and per-window scene filters work in Conky Studio; from the project model through codegen, Live Preview, and Manager launch. It also covers compatibility and limitations so you can judge whether your setup is a good fit.


Overview

A Conky Studio project can drive one or more Conky processes, each with its own:

Concern What it is
Window Geometry, alignment, gap, FPS, transparency, window type, optional monitor pin
Conf One conky.conf (primary) or conky_<id>.conf (extra windows)
Scene Which visual nodes that window actually draws (optional filter)
Shared data Sources + logic still refresh fully so all windows see coherent values

start.sh launches every enabled window under one process group (same lock/stop behaviour as single-window themes).


Will it work for me? (Compatibility)

Multi-window support is fully implemented in Studio (project model → build → start.sh → Manager). How well it behaves depends mainly on your display server, window type, and whether monitors stay stable between build and run.

Good fit (likely to work)

  • X11 session (most traditional desktop setups, many KDE/Xfce/i3 setups)
  • Window layering set to Auto or Normal (not Desktop/Dock experiments)
  • Monitors already connected when you Build & Install (or when Manager applies a pin)
  • One primary HUD + one or two extra windows (e.g. second monitor clock / mini panel)
  • Same machine for design and daily use (head indices match what discovery saw at build time)
  • Optional scene filters so each window draws a subset of the same graph

Possible with care (test on your machine)

  • Multi-GPU or unusual output naming (pin the correct monitor name; rebuild if the wrong screen lights up)
  • HiDPI/mixed-scale monitors (Conky placement can be finicky; prefer Normal + explicit gaps)
  • Plasma/wlroots Wayland where Conky overlays are known to work for single windows; multi-process may work, but treat it as experimental on your compositor
  • Desktop or Dock window types, sometimes required for “stick to desktop,” but they are a common source of X BadWindow / early exit if the head or WM disagrees

Poor fit (often fails or is unsupported)

  • GNOME on Wayland — Studio’s own hardware notes: overlays often cannot host properly regardless of multi-window
  • Expecting Live Preview to show all monitors at once; preview runs one conf at a time, forced to Normal, with no xinerama_head
  • Frequent hotplug (laptop dock, lid, TV unplug) without rebuilding or re-pinning; head index can go stale
  • Assuming one window’s size/scene automatically differs per monitor without adding windows/scene filters in the Windows panel

Quick decision table

Your situation Expectation
X11, Normal windows, 2 monitors, build on the PC you use daily High chance it works after Build & Install
Scene filter only (subset of visuals per window) once multi-conf launches High
Desktop/Dock + specific monitor pin Medium — try Normal first if you see crashes
GNOME Wayland Low for overlays in general
“Preview proves multi-monitor placement” Low — use installed start.sh / Manager for the real test
Unplug monitors often, never rebuild Low until you re-pin/rebuild

Practical test: Build & Install → Manager Start (or ./start.sh) → confirm each process appears on the intended output. Do not rely on Live Preview alone for multi-monitor sign-off.


Limitations

These are intentional design constraints or known sharp edges in the current implementation—not incomplete TODOs in the Windows panel itself.

Platform and windowing

  • Wayland (especially GNOME) may not allow Conky-style overlays at all; multi-window cannot work around that.
  • Desktop/Dock types attach differently than Normal; combined with a wrong xinerama_head, Conky can die with X BadWindow (often exit-style failures). Live Preview deliberately uses Normal and omits xinerama_head to reduce that race; installed themes still emit pins when you set them.
  • Monitor pin uses discovery at build (and optionally Manager’s theme.json monitor field). It is not a continuous “follow this display forever” service.

Live Preview vs installed theme

  • Preview = one window, temp build, daemon scripts primed once (no full start.sh poll loops).
  • Placement on a second monitor in daily use is validated by installed launch, not by the preview dock.

Data and layout model

  • One node graph for the whole project. Windows do not own separate graphs; they share sources/logic and optionally filter which visuals paint.
  • A node has one set of size/position props for all windows. Per-monitor different sizes of the same node are not supported—duplicate nodes or accept one geometry.
  • Scene filters store visual node ids. Deleted nodes can leave stale ids; codegen falls back to the full draw list if the filter matches nothing—rebuild after large graph edits.
  • Daemon-mode sensors (and similar families) are theme-global: one script/cache family, not one per window.

Manager and export

  • Multi-window themes still launch via generated start.sh (all confs in one process group).
  • Manager’s monitor combo writes theme.json; Studio builds can already embed xinerama_head in each conf. Behaviour when both are used on complex multi-conf themes should be checked after install.
  • Older tools that only read primary resolution from theme.json ignore the optional windows array.

UI misconceptions

  • Canvas → Multi-window/multi-monitor only shows/hides the Windows dock. It does not enable multi-monitor by itself—you must Add windows and build/install.
  • Hiding the dock does not remove windows or scene filters from the project.

Windows (project model)

Windows live on the project as a list of WindowSettings (see Project.ensure_windows(), primary_window(), enabled_windows()).

Typical fields per window:

  • id — stable identity (primary is special for naming)
  • name — label in the Windows panel
  • monitor"auto" / "primary" or a concrete output name
  • width / height, alignment, gap_x / gap_y
  • fps, transparent, window_class
  • window_typeauto | normal | desktop | dock (resolved at build for the session)
  • enabled — disabled windows are not built/launched
  • z — ordering for stable build/list order
  • visible_node_ids — optional scene filter (list of visual node ids)

The Canvas node still holds the single-HUD defaults. The primary window stays in sync with canvas size/alignment/etc. (sync_canvas_from_primary / sync_canvas_from_node). Extra windows can diverge (second monitor size, different gap, etc.).

UI: Windows panel

Studio → Windows dock (shown when Canvas → Multi-window/multi-monitor is checked; that checkbox only toggles dock visibility, not the data).

You can:

  • Add/remove windows (at least one always remains)
  • Edit name, monitor, size, alignment, window type, gaps, enabled
  • Preview this window — Live Preview targets that conf
  • Use visible layers as scene — snapshot current Layers eye-open visuals into visible_node_ids
  • Clear scene filter — draw the full shared graph again

Monitor choices come from hardware discovery (discovery.monitor_choices_for_ui()). A concrete monitor can become Conky’s xinerama_head at build time when resolvable.


Build output layout

builder.build_project(...) writes a theme directory, for example:

MyHUD/
  start.sh
  theme.json          # resolution from primary; optional "windows" bookkeeping
  README.md
  conky.conf          # primary window
  conky_<safe_id>.conf  # each extra enabled window
  render.lua          # full shared graph (always written)
  render_<safe_id>.lua  # only when that window has a non-empty scene filter
  scripts/
  images/
  assets/
  fonts/

Conf generation (conky_conf_gen)

Each enabled window gets its own conf body:

  • Self-locating lua_load pointing at that window’s Lua basename (render.lua or render_<id>.lua)
  • lua_draw_hook_post = 'main_draw'
  • Window type resolved for the session (Live Preview forces normal and skips xinerama_head to avoid BadWindow races)
  • Optional xinerama_head when monitor is pinned and discovery finds an index
  • Size/alignment/gaps/FPS/transparency from that window
  • Shared canvas_ext plugin directives applied to every conf

Primary keeps the classic name conky.conf for compatibility; others use conky_<sanitized_id>.conf.

Lua generation (lua_gen.build_render_lua)

  • Sources and logic always refresh fully (so two windows sharing CPU % stay consistent).
  • Every visual still gets a draw_node_* function in the shared render.lua when building the full graph.
  • If visible_node_ids is non-empty for a window, a filtered file is written: main_draw only calls the listed visual draw functions (with a safe fallback to full set if the filter would be empty after deletes).

Scene filter is therefore a draw list, not a separate graph: data plane is shared; paint plane can be subsetted per window.

start.sh (start_sh_gen)

  • Daemon-mode scripts (and album-art pollers, unwired daemon custom scripts, etc.) still start once for the whole theme.
  • One conky -c … per conf basename; the last conf is exec’d so the process group stays alive.
  • Multi-window builds emit a build warning counting primary + extra processes.

theme.json

  • Core meta uses primary resolution for older tooling.
  • An optional windows array records id, name, monitor, resolution, conf basename, enabled (ignored by older readers).

Scenes (visible_node_ids)

What a scene is

A scene filter is a list of visual node ids stored on a window. At build time:

  1. Full render.lua is always produced (shared library of draw functions + refresh).
  2. If the list is non-empty, a second Lua file loads the same framework and sources but only schedules the filtered visuals in main_draw.

Non-visual nodes (sources, logic, module-mode Custom Lua) are not “in” or “out” of the scene in the paint sense; they still run so values exist for whatever is drawn.

How to set a scene in Studio

  1. Use Layers to show/hide (eye) the visuals you want on a given monitor layout.
  2. Select the target window in Windows.
  3. Click Use visible layers as scene.

Clear with Clear scene filter.

There is no separate “scene document”; the filter is just membership of existing graph nodes.

Design intent

Goal Mechanism
Same sensors on two monitors Shared refresh_sources
Different chrome/gauges per monitor Per-window visible_node_ids
Don’t duplicate the whole project One graph, multiple conf + optional filtered Lua
Manager/export still “one folder” Multiple confs + one start.sh

Live Preview

LivePreviewController:

  • Builds into a temp dir with for_preview=True behaviour from the builder path (window type forced normal, no xinerama head) where applicable.
  • Does not run the full daemon loops from start.sh; it primes daemon caches once then runs one Conky process against the selected conf.
  • Preview window is chosen via Windows panel (“Preview this window”) or the preview panel’s selector (preview_window_id: "primary" or a window id → matching conf path).

Debounced rebuilds + graceful stop reduce X BadWindow races when relaunching.


Manager & installed themes

  • Installed themes under ~/.config/conky/ may set a monitor pin in theme.json (ThemeMeta.monitor); Manager’s combo writes that field and process start can pass it through.
  • Multi-window themes still start via the generated start.sh (all confs). Pinning behaviour for multi-process themes depends on how the process manager applies monitor overrides to each conf; Studio builds already embed xinerama when resolved at export time.
  • Export/install is the same folder layout as Build & Install from Studio.

Canvas checkbox vs real multi-window

Canvas property Effect
Multi-window/multi-monitor (show_windows_panel) Only shows/hides the Windows dock

Enabling extra windows is done by Add in the Windows panel (and saving the project). Unchecking the panel does not remove windows or scene filters from the project.


End-to-end flow

Project.windows[]  (+ optional visible_node_ids per window)
        │
        ▼
builder.build_project
        │
        ├─► scripts/images/assets (shared)
        ├─► render.lua (full)
        ├─► render_<id>.lua (if scene filter)
        ├─► conky.conf + conky_*.conf
        ├─► start.sh (all confs)
        └─► theme.json (+ windows metadata)
        │
        ▼
./start.sh  →  N Conky processes, shared daemon pollers

Live Preview shortcuts the same build but runs a single selected conf without long-lived poll loops.


Practical tips

  1. Primary window should match the “main” canvas size you edit most; Position Stage/canvas sync revolve around it.
  2. Prefer window type Normal on problematic multi-monitor or preview setups; desktop/dock + wrong head is a common BadWindow source (documented in builder and conf gen).
  3. Scene filters should list visual ids only; after deleting nodes, rebuild so stale ids don’t leave an empty filter (codegen falls back to full draw list if the filter matches nothing).
  4. Sensors in daemon mode are still theme-global; two windows do not double-spawn family scripts; one script family, shared cache.
  5. For a “full HUD left, clock-only right” layout: duplicate visuals as needed or filter scenes so the right window only paints the clock/text nodes.
  6. After changing monitors (dock, HDMI, rearrange), rescan, re-check pins, and rebuild if a window appears on the wrong screen or fails to start.
  7. Confirm real multi-monitor behaviour with Manager Start or ./start.sh, not Live Preview alone.

Related source map

Area Primary modules
Build orchestration codegen/builder.py
Conf text codegen/conky_conf_gen.py
Lua + scene filter codegen/lua_gen.py (build_render_lua(..., visible_node_ids=...))
Launch script codegen/start_sh_gen.py
Live Preview preview/live_preview.py
Windows UI ui/studio/windows_panel.py
Studio wiring ui/studio/studio_tab.py
Canvas toggle nodes/canvas.py (show_windows_panel)

Multi-window and scene filters are implemented end-to-end; success on a given desktop still depends on session type, window layering, and stable monitor topology between build and run.

Clone this wiki locally