Skip to content

Desktop widgets (transparent background) and an audio widget sample - #25

Merged
BuddhaCodes merged 2 commits into
masterfrom
feature/widget-sketches
Nov 2, 2026
Merged

BuddhaCodes merged 2 commits into
masterfrom
feature/widget-sketches

Conversation

@BuddhaCodes

Copy link
Copy Markdown
Owner

Built on top of #24 (it includes its commits): merge #24 first, and this PR's diff then shrinks to the widget commit alone.

Widgets

A sketch calls Widget() in Settings() and runs as a desktop widget:

  • No borders or title bar. Stays above other windows (alwaysOnTop). Dragging it anywhere moves it (draggable: false → Alt + drag, so left clicks reach the sketch).
  • See-through background: what Clear() leaves (and any alpha below 255) shows the desktop. IsTransparentWindow says whether the system granted it. Windows and macOS do; Linux only with a compositor. Without it, those pixels come out black and the sketch draws a Background().
  • Right-click: always on top, close. It reopens where you left it (top-right corner the first time), per sketch class.
  • WindowX/WindowY: the window's position on screen, for inertia.

How it works: the canvas already keeps alpha end to end (a premultiplied RGBA offscreen surface blitted over a cleared lease). What was missing was the window: Background = Transparent plus TransparencyLevelHint = Transparent, read back from ActualTransparencyLevel.

Where it applies:

  • IDE: Run opens the widget on the desktop and the canvas shows a card. Stop/Run/Hot Reload/pause/crashes work as usual, and closing the widget ends the run. Sample previews stay inline.
  • Exports, the fast-run window and SketchApp.Run() (NuGet/VS Code): the window itself becomes the widget. Settings() now runs before the window shows, and only once.

Audio widget sample

The TerminalAudio blobs on a transparent widget (560×220):

  • Lows on the left and highs on the right; in silence the blobs come loose and float.
  • They swing when you drag the widget.
  • On macOS and Linux (no system-audio capture) they move in a demo mode.

Also

  • Placeholder text wraps between words (it used to cut words).
  • SketchApp picks the host's UI language from the system.
  • Docs: a Widget entry in Sketch structure, keywords, and examples.json (87 examples).

Checks

  • 616 .NET tests (8 new) and 15 extension tests pass.
  • Under Xvfb:
    • Without a compositor: the opaque fallback.
    • With xcompmgr: real per-pixel transparency over the desktop.
    • Placement: top-right corner.
  • IDE flow tested with an embedded canvas: card shown, Stop closes the widget (OnStop ran), Run reopens it, closing the widget stops the run.

Generated by Claude Code

- Sketch.Widget(transparent, alwaysOnTop, draggable), called in
  Settings(): no borders, a see-through background where the system
  allows it (IsTransparentWindow says), above other windows, moved by
  dragging, a right-click menu, and its position remembered per sketch.
  WindowX/WindowY give the window's position for inertia effects.
- AvaloniaSketchWindow runs Settings() before showing so it can become
  the widget; the IDE's canvas opens it on the desktop and shows a card,
  with Stop, Run, Hot Reload, pause and crashes going through as usual.
  Sample previews stay inline.
- Audio widget sample: the audio-reactive terminal's blobs on a
  transparent widget; they swing when it's dragged; demo motion where
  there's no system-audio capture (macOS, Linux).
- Card text now wraps between words; SketchApp picks the host's UI
  language from the system.
- Docs (Widget entry), keywords, examples.json and reference index
  updated; tests for the API, placement and the sample.
@BuddhaCodes
BuddhaCodes merged commit 9ef1a52 into master Nov 2, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant