-
-
Notifications
You must be signed in to change notification settings - Fork 1
Multi window support
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.
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).
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.
- 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
- 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
- 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
| 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.
These are intentional design constraints or known sharp edges in the current implementation—not incomplete TODOs in the Windows panel itself.
- 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 omitsxinerama_headto reduce that race; installed themes still emit pins when you set them. - Monitor pin uses discovery at build (and optionally Manager’s
theme.jsonmonitor field). It is not a continuous “follow this display forever” service.
- Preview = one window, temp build, daemon scripts primed once (no full
start.shpoll loops). - Placement on a second monitor in daily use is validated by installed launch, not by the preview dock.
- 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.
- 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 embedxinerama_headin each conf. Behaviour when both are used on complex multi-conf themes should be checked after install. - Older tools that only read primary
resolutionfromtheme.jsonignore the optionalwindowsarray.
- 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 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_type —
auto|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.).
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.
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/
Each enabled window gets its own conf body:
- Self-locating
lua_loadpointing at that window’s Lua basename (render.luaorrender_<id>.lua) lua_draw_hook_post = 'main_draw'- Window type resolved for the session (Live Preview forces
normaland skipsxinerama_headto avoid BadWindow races) - Optional
xinerama_headwhen monitor is pinned and discovery finds an index - Size/alignment/gaps/FPS/transparency from that window
- Shared
canvas_extplugin directives applied to every conf
Primary keeps the classic name conky.conf for compatibility; others use conky_<sanitized_id>.conf.
- Sources and logic always refresh fully (so two windows sharing CPU % stay consistent).
-
Every visual still gets a
draw_node_*function in the sharedrender.luawhen building the full graph. - If
visible_node_idsis non-empty for a window, a filtered file is written:main_drawonly 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.
- 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 isexec’d so the process group stays alive. - Multi-window builds emit a build warning counting primary + extra processes.
- Core meta uses primary resolution for older tooling.
- An optional
windowsarray records id, name, monitor, resolution, conf basename, enabled (ignored by older readers).
A scene filter is a list of visual node ids stored on a window. At build time:
- Full
render.luais always produced (shared library of draw functions + refresh). - 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.
- Use Layers to show/hide (eye) the visuals you want on a given monitor layout.
- Select the target window in Windows.
- 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.
| 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
|
LivePreviewController:
- Builds into a temp dir with
for_preview=Truebehaviour from the builder path (window type forcednormal, 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.
- Installed themes under
~/.config/conky/may set a monitor pin intheme.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 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.
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.
- Primary window should match the “main” canvas size you edit most; Position Stage/canvas sync revolve around it.
- 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).
- 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).
- Sensors in daemon mode are still theme-global; two windows do not double-spawn family scripts; one script family, shared cache.
- 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.
- After changing monitors (dock, HDMI, rearrange), rescan, re-check pins, and rebuild if a window appears on the wrong screen or fails to start.
- Confirm real multi-monitor behaviour with Manager Start or
./start.sh, not Live Preview alone.
| 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.