Files
2026-11-04 14:29:22 -06:00

141 lines
5.7 KiB
Markdown

# LiveWall plugin SDK
LiveWall 1.8.0 and later can be extended by **plugins**: .NET 8 assemblies that LiveWall loads at
start-up and hands a context object. A plugin can add wallpaper renderers, draw on the desktop, add
settings pages, add commands and tray entries, register hotkeys, rewrite wallpaper requests, and read
the same events the app itself uses.
> **Plugins are third-party code.** They run inside LiveWall's process with your rights. LiveWall does
> not review, sign or sandbox them, and unverified plugins may cause harm to your computer. The user
> is shown a warning listing the plugin's exact file hash and every permission it declared before it is
> allowed to run — see [security.md](security.md).
---
## Contents
| Document | What it covers |
|---|---|
| [getting-started.md](getting-started.md) | From an empty folder to a running plugin in ten minutes |
| [api-reference.md](api-reference.md) | Every interface, member and enum in `LiveWall.Sdk` |
| [extension-points.md](extension-points.md) | Overlays, renderers, filters, pages, commands, hotkeys — with the caveats |
| [events.md](events.md) | The event catalogue, threading rules and lifetime |
| [security.md](security.md) | Permissions, trust, hashes, the warning dialog, threat model |
| [packaging.md](packaging.md) | Folder layout, versioning, checksums, distribution, updates |
| [troubleshooting.md](troubleshooting.md) | "My plugin does not load", reading the log, unload rules |
| [examples.md](examples.md) | Copy-paste recipes for the common shapes |
The SDK itself is `LiveWall.Sdk.dll` — a small contract assembly. Plugins reference it and nothing
else; `LiveWall.exe` is deliberately *not* a dependency.
---
## What a plugin can change
| Extension point | Interface | Typical use |
|---|---|---|
| Desktop overlay | `IWallpaperOverlay` | Clock, now-playing badge, visualiser, watermark, fps counter |
| Wallpaper renderer | `IWallpaperRendererPlugin` + `IWallpaperRenderer` | Shaders, emulators, animated 3D scenes, a custom video pipeline |
| Wallpaper filter | `IWallpaperFilter` | Resolve short links, pick a random source, block changes, add metadata |
| Settings page | `IPluginSettingsPage` | Your own configuration UI inside LiveWall |
| Command | `PluginCommand` | "Next quote", "Toggle rain", anything the user can trigger |
| Tray entry | `PluginCommand` + `TrayMenu` permission | Same commands, reachable with two clicks |
| Hotkey | `PluginHotkey` | Global shortcut for a plugin action |
| Events | `IPluginEvents` | React to wallpaper/playback/session changes |
| Host actions | `IHostActions` | Set the wallpaper, play/pause, notify, open settings |
| Storage | `IPluginStorage` | Persist your own JSON state, own folders |
Everything is registered through `IPluginContext.Extensions` inside `Initialize`. There is no
"unregister everything" step: LiveWall drops all of a plugin's registrations when it unloads it.
---
## How loading works (short version)
```
%APPDATA%\LiveWall\plugins\
└── com.example.clock\ ← one folder per plugin, any name
├── plugin.json ← identity + permissions (required)
├── ClockOverlayPlugin.dll ← entry assembly
└── (any other files you need)
```
1. LiveWall scans the plugin folder at start-up (and whenever the user presses **Rescan**).
2. `plugin.json` is validated: API version, host version, optional checksum.
3. Plugins the user has **not** enabled stay on disk, unloaded, listed in **Plugins ▸ Installed plugins**.
4. Enabling runs the warning dialog. Only after the user accepts is the assembly loaded — into a
collectible `AssemblyLoadContext` — and `ILiveWallPlugin.Initialize(context)` called.
5. Any exception in `Initialize` marks the plugin **Failed** and shows the message. The app keeps
running; a plugin can never take LiveWall down.
Full details in [packaging.md](packaging.md) and [troubleshooting.md](troubleshooting.md).
---
## Quick start
```bash
dotnet new classlib -n MyPlugin -f net8.0-windows
```
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="path\to\LiveWall.Sdk\LiveWall.Sdk.csproj">
<Private>false</Private>
</ProjectReference>
</ItemGroup>
</Project>
```
```csharp
using LiveWall.Sdk;
public sealed class MyPlugin : ILiveWallPlugin
{
public void Initialize(IPluginContext context)
=> context.Host.ShowNotification("MyPlugin", "Hello from the wallpaper!");
public void Shutdown() { }
}
```
```json
{
"id": "com.example.myplugin",
"name": "My plugin",
"version": "1.0.0",
"author": "you",
"description": "Does one small thing.",
"apiVersion": "1.0",
"entry": "MyPlugin.dll",
"type": "MyPlugin",
"minHostVersion": "1.8.0",
"permissions": ["Commands"]
}
```
Copy the build output next to the manifest, then use **Plugins ▸ Rescan** and **Enable**.
The repository ships a complete, buildable example in `samples/ClockOverlayPlugin/` that uses every
extension point — read it next to [extension-points.md](extension-points.md).
---
## Stability promise
The contracts live in `LiveWall.Sdk` and are versioned separately from LiveWall's own version:
* `PluginApi.Version` (currently **1.0**) is what `plugin.json` must declare.
* Adding members to an existing interface would break compiled plugins, so new capabilities arrive as
**new optional interfaces**, and the major version only changes if something must be removed.
* `minHostVersion` in the manifest refuses to run on an older LiveWall instead of failing mysteriously.
See [packaging.md](packaging.md#versioning).