-
-
Notifications
You must be signed in to change notification settings - Fork 60
Create Web Architecture
This page explains, end to end, how a Web wallpaper actually runs inside Sucrose: how the page is served (a local HTTP server, not file://), how live audio and system data flows from the Backgroundog service across an inter-process channel into your page's JavaScript callbacks, how customization properties are pushed on start and on change, and how mouse and keyboard input reaches your page. It is the developer-facing companion to the creator pages — read it to understand the moving parts behind Create Audio API, Create System API, and Create Property Listener Filters.
- The processes involved
- Step 1: Engine launch and the local HTTP server
- Step 2: Properties applied on init
- Step 3: The live-data pump
- Step 4: ExecuteScriptAsync into the page
- Step 5: Input forwarding
- The data bundle
- Transport selection
- End-to-end sequence
- Why this matters to creators
- See also
A running Web wallpaper spans several separate Windows processes that coordinate over inter-process channels (Sucrose is multi-process by design — see Architecture Overview):
| Process | Role in a Web wallpaper |
|---|---|
Live engine (Sucrose.Live.WebView or Sucrose.Live.CefSharp) |
Hosts the browser, serves the page, runs JavaScript, receives the data bundle, and calls your callbacks. |
| Sucrose.Backgroundog | Captures audio (WASAPI loopback → FFT) and polls hardware/media-session info, then ships a bundle to the engine. |
| Sucrose.Commandog | Launches the engine process (via its Live command) when you apply a wallpaper. The type → engine mapping itself is resolved upstream by the shared Sucrose.Shared.Live.Helper.Run.Start() launch logic (which reads SucroseInfo.json's Type and looks up the configured engine) before the Live command is dispatched to Commandog. |
| Sucrose.Launcher / Sucrose.Portal | UI and tray; trigger apply/restart and push customization changes. |
Only WebView and CefSharp participate in this data channel. The Backgroundog data pump is web-engine-only — MpvPlayer, VlcPlayer, Aurora, Nebula, Vexana, and Xavier do not receive the audio/system bundle. See Choosing Engines.
When you apply a Web wallpaper:
- Sucrose reads the theme's
SucroseInfo.json, seesTypeisWeb(value2), and picks the configured engine for that type. - The Live engine starts and, for a Web type, sets its source to your entry file (
Sourcefrom the manifest, for exampleMatrix.html). - Local web content is served by an internal HTTP server (
LocalHttpServer) onhttp://localhost:{port}/andhttp://127.0.0.1:{port}/, where{port}is a free loopback port chosen automatically at startup. Content is served over HTTP, notfile://— this matters because some browser security restrictions (modules, fetch, WebGL texture loads) behave differently underfile://.
Gif, Video, and YouTube types are loaded through generated HTML wrappers (GifContent.html, VideoContent.html, YouTubeContent.html); the Url type points the engine straight at the remote URL.
On initialization, the engine reads your SucroseProperties.json (or an encoded variant) and applies all current property values by calling your SucrosePropertyListener once per property. This means your wallpaper always starts in the user's last-saved configuration — you do not need to read settings yourself. See Create Property Listener Filters and Create Customization Controls.
When the user later changes a control in the Portal, the engine's FileSystemWatcher detects the updated properties file and re-pushes the changed values to the running page via the same call — live, no restart. The trigger file is cleaned up after ~3 seconds.
Independently of properties, the Backgroundog service runs a periodic timer. On each tick it:
- Calls a
Get*Info()collector for each category:Bios,Date,Audio,Memory,Battery,Graphic,Network,Storage,Processor,Motherboard. - Builds a single
Backgroundogpayload object (ten nullable JSON sub-objects) and serializes it to JSON. - Sends it to the engine over the active transport — exactly one of Pipe, Signal, or Transmission (see below). The producer (Backgroundog) is the client; the engine is the server.
Audio specifically comes from WASAPI loopback capture run through an FFT, producing the Data magnitude spectrum (MaxSample = 128 samples) used by visualizers — see Create Audio API. Hardware and media-session info is polled by the same service — see Backgroundog Service.
On the engine side, the transport's handler receives the JSON, deserializes it back into the Backgroundog payload, and stores each non-null sub-object as a JSON string in the engine's internal fields (AudioData, ProcessorData, MemoryData, …). Then, for each non-empty hook you declared in SucroseCompatible.json, the engine formats your template with the stored JSON (string.Format(hook, json)) and runs it via ExecuteScriptAsync on the WebView2/CefSharp page. That call invokes your JavaScript function:
// You declared: "SystemAudio": "SucroseAudioData({0});"
// The engine runs: SucroseAudioData({ "Data":[...], "Title":"...", ... });
window.SucroseAudioData = function (obj) { spectrum = obj.Data; };If a hook string is empty (or you never declared it), the engine does not fire it — so you only pay for the data categories you request.
When the desktop is focused, mouse and keyboard activity is forwarded into the page. The browser engines reference Sucrose's raw-input layer, translating raw input into Win32 messages (and a synthetic scroll script) so that standard web events — mousemove, click, wheel, keydown — fire inside your wallpaper. This is what makes Web wallpapers interactive (for example, the Fluid Simulation Showcase reacts to the cursor). See Type-Web.
The bundle that crosses the channel is the same regardless of transport — ten nullable JSON sub-objects:
Bios, Date, Audio, Memory, Battery, Graphic, Network, Storage, Processor, Motherboard
Each non-null sub-object is re-serialized on the engine side and fanned out to its matching SucroseCompatible.json hook. The Audio sub-object is the audio-reactive channel; the other nine are the System Status API. Field-by-field documentation lives on Create Audio API and Create System API.
The live-data channel can use one of three interchangeable transports, chosen by the CommunicationType setting (default Transmission). They carry the identical JSON payload — only the carrier differs.
| Transport | Mechanism | Channel name |
|---|---|---|
| Transmission (default) | TCP on the loopback address (127.0.0.1) at a dynamically allocated port (saved to TransmissionPort) |
created on demand |
| Pipe | Named pipe (System.IO.Pipes) |
Sucrose.Wallpaper.Engine.Backgroundog.Pipe |
| Signal | JSON file + FileSystemWatcher under %AppData%\Sucrose\Cache\SignalT
|
Backgroundog.sgnl (with GUID-suffixed instances) |
The engine picks the transport from CommunicationType and stands up exactly one server; Backgroundog reads the same setting (and the engine-set *Required/TransmissionPort flags) to know which client to use. Full details, including the Launcher tray-control channel, are on the IPC page.
[Sucrose.Backgroundog] [Sucrose.Live.WebView | CefSharp]
periodic timer
collect Bios/Date/Audio/Memory/Battery/
Graphic/Network/Storage/
Processor/Motherboard (JObject)
build Backgroundog payload -> JSON
send over CommunicationType transport ----> server receives JSON
(Pipe | Signal | Transmission) deserialize -> Backgroundog payload
store each non-null field as JSON string
for each non-empty SucroseCompatible hook:
string.Format(hook, json)
ExecuteScriptAsync(js) ----> page JS
SucroseAudioData(obj)
SucroseProcessorData(obj)
...
(separately) properties applied on init and on change -> SucrosePropertyListener(name, val)
(separately) raw mouse/keyboard -> Win32 messages -> page events
sequenceDiagram
participant BG as Backgroundog
participant Eng as Browser engine
participant Page as Wallpaper page
Note over Eng: on apply: start local HTTP server, serve theme
Eng->>Page: SucrosePropertyListener (init values)
loop each tick
BG->>BG: collect 10 categories, build payload, to JSON
BG->>Eng: send over Pipe / Signal / Transmission
Eng->>Eng: deserialize, store as JSON strings
Eng->>Page: for each hook, ExecuteScriptAsync
Note over Page: SucroseAudioData(obj), SucroseProcessorData(obj), ...
end
Note over Eng,Page: property change: FileSystemWatcher then SucrosePropertyListener
Note over Eng,Page: raw mouse/keyboard then Win32 messages then page events
-
You receive data; you do not poll for it. Implement the
Sucrose*Datacallbacks and Sucrose calls them on each tick — there is no API to request a reading on demand. -
Serve-over-HTTP changes behavior vs
file://. Relative paths, modules, fetch, and WebGL all run againsthttp://localhost:{port}/, so author your page as if it were on a tiny web server. -
Declare only the hooks you use. Each enabled hook adds collection and
ExecuteScriptAsyncwork; unused categories are never pushed. -
Properties arrive on start and on every change. Keep
SucrosePropertyListenercheap and idempotent — it is called repeatedly, including for live re-application. - Interactivity is automatic on the browser engines when the desktop is focused; build with normal DOM event listeners.
- Web-engine only. The whole data pump, JS bridge, and input forwarding apply to WebView/CefSharp. If your callbacks never fire, confirm the wallpaper is running on a browser engine. See Choosing Engines.
-
Create Audio API — the
SucroseAudioDatapayload (FFT + now-playing) - Create System API — the nine system-status callbacks
- Create Property Listener Filters — how property changes reach your page
- IPC — Pipe/Signal/Transmission transports in depth
- Backgroundog Service — the data producer
- Type-Web — the Web wallpaper type
- Engine-WebView and Engine-CefSharp — the browser engines
Getting Started
- Installation
- System Requirements
- Quick Start
- Portal Interface Tour
- Updating Sucrose
- Uninstalling Sucrose
Wallpaper Types
Using Sucrose
- Managing Library
- Using Store
- Customizing Wallpaper
- Multi-Monitor
- Wallpaper Cycling
- Choosing Engines
- Performance Rules
- Theme, Tray & Startup
- Discord Rich Presence
Settings Reference
- Settings Overview
- Settings: General
- Settings: Personal
- Settings: Performance
- Settings: Wallpaper
- Settings: System
- Settings: Other
- Settings: All Keys
Creating Wallpapers
- Create Overview
- Create: Step By Step
- Create: Package Format
- Create: Customization Controls
- Create: JS Bridge
- Create: Audio API
- Create: System API
- Create: Property Listener & Filters
- Create: Web Architecture
- Create: Compatibility
- Create: Example Wallpapers
- Create: Sharing & Publishing
Engine Reference
- Engines Overview
- Engine: MpvPlayer
- Engine: VlcPlayer
- Engine: WebView
- Engine: CefSharp
- Engine: Nebula
- Engine: Vexana
- Engine: Xavier
- Engine: Aurora
- Engine Comparison
Automation & Command Line
Architecture & Internals
- Architecture Overview
- Lifecycle
- Commandog Dispatcher
- Single-Instance Mutexes
- IPC
- Backgroundog Service
- Crash Reporting
- Update Internals
- Property Service
- Undo Internals
Data, Files & Diagnostics
Building & Contributing
- Building From Source
- Repository Layout
- Shared Item Projects
- Code Conventions
- Preprocessor Symbols
- Publish Pipeline
- Bundle Installer Internals
- Extending Sucrose
- Contributing
- Translating with Localizer
- Localization Coverage
- Security Policy
- Privacy & Telemetry
Help & Support